PAGE 60,132 TITLE CHKboot - High performance boot sector checker ; SUBTTL General program description and use of common storage ; ----------------------------------------------------------------------------; ; CHKboot - check DOS boot record and partition table boot for changes.; ; ----------------------------------------------------------------------------; ; CHKBOOT 1.0 þ PCDATA TOOLKIT Copyright (c) 1990 Ziff Communications Co. ; ; PC Magazine þ Wolfgang Stiller ; ; ; ;-----------------------------------------------------------------------------; ;Purpose: ; ;CHKBOOT checks the integrity of DOS boot sectors and hard disk ; ;partition tables (sectors). On first execution, or with the "/I" ; ;parameter, CHKBOOT writes check values to the parameter file and ; ;creates reload files for the boot and partition sectors. All files ; ;written contain self check information. CHKBOOT subsequently will ; ;check the DOS boot record and/or the partition sector for any changes ; ;by using information recorded on the parameter file. ; ; ; ; ----------------------------------------------------------------------------; ;Format: ; ; ; ;CHKBOOT [filespec] [/B] [/H] [/I] [/P] [/2] ; ; ; ;"filespec" is optional file specification for the parameter file. If not ; ; specified, "CHKBOOT.PRM" will be used as the parameter file. ; ;"/H" Presents extensive detailed help information. ; ;"/B" Checks boot record on current DOS disk for any changes. ; ;"/P" Checks partition sector on first physical hard disk for any changes. ; ;"/2" Checks partition sector on second physical hard disk. ; ; /P and /2 may not be specified together. ; ;"/I" Force initialization. Attempts read of current boot sector and ; ; partition sector on 1st hard drive (Include /2 for 2nd partition ; ; sector). CHKBOOT then writes the parameter file so that any ; ; changes to these sectors can be detected on subsequent ; ; executions. The boot and partition sectors are copied to files ; ; @@BOOT.SCT and @@PARTIT.SCT for LODboot reload. ; ; ; ; At least one of the parameters, /B /P /2 or /I must be entered. ; ; If /I is entered then /B and /P are ignored if entered (/2 is ; ; honored). ; ; ; ;Note, If the parameter file does not exist, then CHKBOOT will ; ; automatically initialize and create the file. ; ; ; ;Example: "CHKBOOT /B /F" will read both the DOS boot sector and the ; ; partition sector on the 1st hard drive and compare the ; ; cryptographic checksums from a prior execution. ; ;-----------------------------------------------------------------------------; ;Remarks: ; ; It is safest to keep CHKBOOT and all its files off-line on a floppy. ; ; This floppy should be bootable (created with FORMAT d:/S). In order ; ; to check hard disk partition sectors, CHKBOOT can be executed ; ; directly from anywhere. To check a DOS boot sector, you must be ; ; logged on to the DOS drive you wish to check. If for example, your ; ; floppy is drive A, and C is your default drive, then ; ; A:CHKBOOT A:CHKBOOT.PRM/B/P ; ; will cause the program and the parameter file (CHKBOOT.PRM) to both ; ; be utilized from floppy. The DOS boot sector from drive C and the ; ; hard disk partition sector from the first physical disk will be ; ; checked. ; ; ; ; All files created by CHKBOOT contain validity check data embedded. ; ; Any change to any of the files will be detected whenever the file is ; ; processed. If CHKBOOT finds corruption to either the parameter file ; ; or the sectors it is checking, it will produce an error message, beep, ; ; and force the user to acknowledge with a key press. Other serious ; ; errors detected are also handled in this way. ; ; ; ; The following DOS errorlevels will be returned on termination. ; ; ; ; 00 - Compare of boot and/or partition records successful. ; ; 02 - Compare of boot sector failed. ; ; 04 - Compare of partition sector failed. ; ; 06 - Compare of both boot and partition boot sectors failed. ; ; 16 - Initialization occurred. No compare done. ; ; 32 - Corruption of the parameter file detected (CHKBOOT.PRM). ; ; 64 - Program failure (usually due to disk problems or lack of space on disk); ;128 - Syntax error on invoking CHKBOOT. ; ; ; ;-----------------------------------------------------------------------------; ;---------------------------------------------------------------; ; Constants: ; ;---------------------------------------------------------------; BOX EQU 254 ;Small box character code CR EQU 0Dh LF EQU 0Ah CRLF EQU 0A0Dh ;Carriage return line feed. Boot_type EQU 0FFh ;Indicator of a boot sector (.PRM) Part_type EQU 055h ;Indicator of a partition sector(.PRM) ; Double line drawing character definitions Horizontal EQU 205 ;Horizontal double line Vertical EQU 186 ;Vertical double line UPRT_corner EQU 187 ;Upper righthand corner UPLT_corner EQU 201 ;Upper lefthand corner LWLT_corner EQU 200 ;Lower lefthand corner LWRT_corner EQU 188 ;Lower righthand corner CSEG SEGMENT ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG SUBTTL Main program ;******************************************************************************; ;** Main program begins here -CHKBOOT- **; ;******************************************************************************; ORG 100H ; THIS IS A COM TYPE PROGRAM CHKBOOT: CALL Parse_parms ;Parse cmdline paramters MOV DX, offset Header_Msg ;Put out title display MOV AH,09H ;DOS display string function INT 21H ; Check system sector size MOV AH,36h ;Check sector size and free space XOR DL,DL ;Check current disk (DL=0 is current) INT 21h MOV Sector_Size,CX ;Save # of bytes per sector CMP CX,512 ;Is this a standard size sector JE Continue_main_process ; If so, continue MOV DX, OFFSET Non_STD_Msg ; Else put out message warning user MOV AH,09h ; DOS display function INT 21h Continue_main_process: XOR BP,BP ;Zero out highest error level code CMP Initialize_Mode,'Y' ;Has init mode been requested? JE Initialize_all_files ; If so, then initialize this program CALL Open_and_Read_PARM_file ;Open and verify existance of parmfile ; If open fails, set initialize flag CMP Initialize_Mode,'Y' ;Check again if INIT is requested... JE Initialize_all_files ; If so, then initialize this program CALL Validate_Parm_File ;Make sure its a valid parm file CMP Boot_wanted,'Y' ;Does user want BOOT rec checked? JNE No_Boot ; If not skip checking the boot rec CALL Read_Boot_Sector ;Do actual read of sector 0 (DOS) ; --------- Calculate cryptographic check/XOR sums for disk sector ----------- MOV SI,offset BUFFER ;Point SI to buffer containing sector MOV CX,Sector_Size ;Process all bytes in a sector CALL Calc_Sums ;Calculate CHK and XOR sums ; On return: DI - Contains checksum for this file ; DX - XOR sum ; ----------------------------------------------------------------------------- CALL Compare_Boot_Sums ;See if any changes to the sector NO_BOOT: CMP Partition_wanted,'Y' ;Does user want Partition checked? JNE End_Execution ; If not skip checking the Partition CALL Read_Part_Sector ;Do actual read of sector 0 (BIOS) ; --------- Calculate cryptographic check/XOR sums for disk sector ----------- MOV SI,offset BUFFER ;Point SI to buffer containing sector MOV CX,Sector_Size ;Process all bytes in a sector CALL Calc_Sums ;Calculate CHK and XOR sums ; On return: DI - Contains checksum for this file ; DX - XOR sum ; ----------------------------------------------------------------------------- CALL Compare_Part_Sums ;Any changes to partition sector? End_Execution: ;Successful termination of program MOV AX,BP ;BP contains highest error level MOV AH,4Ch ;DOS terminate with errorlevel funct INT 21h ;---------------------------------------------------------------------; ; Initialize all files-initialize this program - writing "PARM_File" ; ;---------------------------------------------------------------------; ; This procedure will read both boot and partition records calculate ; ; the check sums (XOR and CHK). These will be recorded on "PARM_FILE".; ;---------------------------------------------------------------------; Initialize_all_files: CALL Create_PARM_file ;Create and open the parameter file MOV DX,offset Init_Msg ;Explain that we are intializing MOV AH,09H ;DOS display string function INT 21H CALL Read_Boot_Sector ;Do actual read of sector 0 (DOS) ; --------- Calculate cryptographic check/XOR sums for disk sector ----------- MOV SI,offset BUFFER ;Point SI to buffer containing sector MOV CX,Sector_Size ;Process all bytes in a sector CALL Calc_Sums ;Calculate CHK and XOR sums ; On return: DI - Contains checksum for this file ; DX - XOR sum ; ----------------------------------------------------------------------------- MOV Boot_XOR_Sum,DX ;Copy XOR sum into PARM buffer MOV SCT_XOR,DX ;Copy XOR sum to reloadable file MOV Boot_CHK_SUM,DI ;Copy CHK sum into Parm buffer MOV SCT_CHK,DI ;Copy CHK sum to reloadable file MOV BYTE PTR[SCT_Type],Boot_type ;Set sector type indicator to BOOT CALL Write_Boot_Sector ;Create a reloadable copy of partition CALL Read_Part_Sector ;Do actual read of sector 0 (BIOS) CMP Partition_wanted,'X' ;Read failed (no longer wanted)? JE Encrypt_Parm_File ; If so, skip writing PARM file ; --------- Calculate cryptographic check/XOR sums for disk sector ----------- MOV SI,offset BUFFER ;Point SI to buffer containing sector MOV CX,Sector_Size ;Process all bytes in a sector CALL Calc_Sums ;Calculate CHK and XOR sums ; ----------------------------------------------------------------------------- MOV Part_XOR_Sum,DX ;Copy XOR sum into memory MOV SCT_XOR,DX ;Copy XOR sum to reloadable file MOV Part_CHK_SUM,DI ;Copy CHK sum into mem MOV SCT_CHK,DI ;Copy CHK sum to reloadable file MOV BYTE PTR[SCT_Type],PART_type ;Set sector type indicator to Part CALL Write_Part_Sector ;Create a reloadable copy of partition Encrypt_Parm_File: ; --------- Calculate cryptographic XOR sum for the PARM file --------------- MOV SI,offset PARM_BUFFER ;Point SI to buffer containing sector MOV CX,41 ;Check 1st 41 characters parm_file CALL Calc_Sums ;Calculate CHK and XOR sums ; ----------------------------------------------------------------------------- MOV PARM_XOR_Sum,DX ;Copy XOR sum into memory MOV PARM_CHK_SUM,DI ;Copy CHK sum into mem CALL Write_Parm_File ;Write records to parmfile MOV AX,4C10h ;DOS terminate with 16 error level INT 21h ;---------------------------------------------------; ; C O M P A R E B O O T S U M S - any changes?; ;---------------------------------------------------; ;Register conventions: ; ; ; ; DI - Contains checksum for this file ; ; DX - XOR sum ; ;---------------------------------------------------; Compare_Boot_Sums: ;See if any changes to the sector CMP Boot_XOR_SUM,DX ;Any change to XOR sum? JNE Boot_change_detected ; If not =, report the change CMP BOOT_CHK_SUM,DI ;Is the checksum OK? JNE Boot_change_detected ; If not, report the change ; ELSE all is OK with boot sector MOV DX,offset Boot_Msg ;Display message about boot record MOV AH,09H ;DOS display string function INT 21H MOV DX,offset OK_Msg ;Explain that all is well MOV AH,09H ;DOS display string function INT 21h RET Boot_Change_detected: ;Report problem with boot record ADD BP,2 ;Adjust DOS error lvl to ind prblm MOV DX,offset Boot_Msg ;Display message about boot record MOV AH,09H ;DOS display string function INT 21H MOV DX,offset Bad_Sector_Msg ;Explain that its bad MOV AH,09H ;DOS display string function INT 21H CALL Send_Beep ;Wake up user! CALL Wait_For_Key ;Beep and force user to hit a key RET ;---------------------------------------------------; ; C O M P A R E P A R T S U M S - any changes?; ;---------------------------------------------------; ;Register conventions: ; ; ; ; DI - Contains checksum for this file ; ; DX - XOR sum ; ;---------------------------------------------------; Compare_Part_Sums: ;See if any changes to the sector CMP Part_XOR_SUM,DX ;Any change to XOR sum? JNE Part_change_detected ; If not =, report the change CMP Part_CHK_SUM,DI ;Is the checksum OK? JNE Part_change_detected ; If not, report the change ; ELSE all is OK with Part sector MOV DX,offset Part_Msg ;Display message about Partition sect MOV AH,09H ;DOS display string function INT 21H MOV DX,offset OK_Msg ;Explain that all is well MOV AH,09H ;DOS display string function INT 21h RET Part_Change_detected: ;Report problem with Partition sector ADD BP,2 ;Adjust DOS error lvl to ind prblm MOV DX,offset Part_Msg ;Display message about Partition sect MOV AH,09H ;DOS display string function INT 21H MOV DX,offset Bad_Sector_Msg ;Explain that its bad MOV AH,09H ;DOS display string function INT 21H CALL Send_Beep ;Wake up user! CALL Wait_For_Key ;Beep and force user to hit a key RET ;---------------------------------------------------; ; R E A D B O O T S E C T O R ; ;---------------------------------------------------; ;Read the DOS boot sector using DOS I/O requests. ; ;---------------------------------------------------; Read_Boot_Sector: PUSH BP ;Save all current registers Try_boot_read_again: ;Come here to retry the extended ;form of the read if normal int 25h failed. Note, it is NOT an error ;that we re-execute the 19h function...some systems require this MOV AH,19h ;DOS get current disk drive function INT 21h ;Get current disk drive in AL (0=A) CMP DOS_Version,4 ;Are we running under DOS 4.x? JNE Old_DOS ;If not, do normal int 25 call ; Process DOS 4.0 disks using extended format of INT25 (handles disks > 32mb) MOV CX,-1 ;Set indicator to handle >32 mb disks MOV BX,Offset INT25_Parms ;Point to 10 byte parameter block MOV Buffer_Segment,DS ;Segment address in parameter block JMP SHORT DOS_Abs_Read ;Do DOS Absolute sector read Old_DOS: MOV CX,1 ;Read just one sector XOR DX,DX ;DX=0 to read DOS logical sector 0 MOV BX,Offset buffer ;Place to put the sector DOS_Abs_Read: INT 25h ;DOS absolute disk read function JNC Boot_read_OK ;If I/O was successful ;Else we had an I/O error ; ; Since some OEM versions of DOS such as COMPAQ 3.31 also support the extended ; format of the int 25h call for disks > 32mb we will lie and say this is ; DOS 4.x and try the interrupt 4.0 using the extended format call. POPF ;Remove flags from stack CMP DOS_Version,4 ;Did we already try DOS 4.x type int? JE Boot_Read_Failed ; If so, then boot read failed ; otherwise try extended int 25h MOV DOS_Version,4 ; Force extended int 25h use (lie) JMP SHORT Try_Boot_Read_Again ; do func 19h and then extd int 25h Boot_Read_Failed: MOV DX,offset Boot_Msg ;Display message about boot record MOV AH,09H ;DOS display string function INT 21H Unrecoverable_IO_Error: ;Exit here if I/O has failed MOV DX,offset IO_Err_Msg ;Explain that input/output failed MOV AH,09H ;DOS display string function INT 21H CALL Send_Beep ;Wake up user! CALL Wait_For_Key ;Beep and force user to hit a key MOV AX,4C40h ; terminate with 64 DOS ERRORLEVEL INT 21h Boot_read_OK: POPF ;restore flags pushed by INT 25h POP BP ;Restore active registers RET ;---------------------------------------------------; ; R E A D P A R T S E C T O R ; ;---------------------------------------------------; ;Read the partition sector using BIOS I/O request ; ;---------------------------------------------------; Read_part_Sector: MOV AH,02 ;BIOS floppy read function of INT 13h MOV DL,BYTE PTR[Drive_number] ;Drive 80 (1st) or 81 (2nd) hard drive MOV AL,1 ;Read only 1 sector MOV CX,1 ;Read (CH) track 0, (CL) sector 1 XOR DH,DH ;Read head number zero MOV BX,Offset buffer ;Place to put the sector INT 13h ;BIOS absolute (floppy) disk read JNC Part_Read_OK ;If I/O was successful ;Else the we had an I/O error MOV DX,offset No_HardDisk_MSG ;Display message about missing part MOV AH,09H ;DOS display string function INT 21H CMP Partition_wanted,'Y' ;Did user ask to read this partition? MOV Partition_wanted,'X' ;Turn off partn checking (stop write) JNE Part_Read_OK ; If user did NOT ask for read,its OK ; Otherwise, its a fatal error JMP SHORT Unrecoverable_IO_Error Part_Read_OK: RET ;---------------------------------------------------------------------------; ; Open_and_read_parm_file: ; ; Open the parameter(CHKBOOT.PRM) file which contains the cryptographic ; ; XOR and checksums for the boot and partition records. ; ; If Open fails, set a flag to indicate this, (intialize_mode=Y) ; ;---------------------------------------------------------------------------; Open_and_Read_Parm_File: MOV AX,3D00h ;Open file for read function MOV DX,offset Parm_File_Name ;Name of the parameter file:ASCIIZ INT 21h ;Do open for read JNC File_found ;If open went OK.. MOV Initialize_mode,'Y' ; If not, force initialization MOV DX,offset Missing_Msg ;Explain that PARM file is missing MOV AH,09H ;DOS display string function INT 21H CALL Send_Beep ;Wake up user! CALL Wait_For_Key ;Beep and force user to hit a key RET File_found: MOV BX,AX ;File handle in BX MOV CX,45 ;Read 45 bytes from disk MOV DX,OFFSET PARM_buffer ;Data to write to disk MOV AH,3FH ;DOS read function INT 21H ;Call DOS JNC Close_Parm_file ;If no error, continue + close file JMP Bad_Parm_file ; else Report that we have a bad file Close_Parm_file: MOV AH,3Eh ;DOS close file function code INT 21h ;Close the file RET ;---------------------------------------------------; ; C R E A T E P A R M F I L E ; ; Does an open create/truncate on the "PARM_file" ; ; Returns file handle in Parm_handle ; ;---------------------------------------------------; Create_PARM_file: ;Create and open the parameter file MOV AH,3Ch ;DOS create file function MOV DX,Offset PARM_File_Name XOR CX,CX ;Set CX (file attribute=normal) = 0 INT 21h JNC Create_Parm_Exit ;IF all went OK then return JMP Unrecoverable_IO_Error Create_Parm_Exit: MOV Parm_Handle,AX ;Save file handle RET ;---------------------------------------------------; ; W R I T E P A R M F I L E ; ;---------------------------------------------------; ;Write the parameter file out to disk. ; ;This is called only during intialization. ; ;---------------------------------------------------; Write_PARM_File: MOV DX,offset PW_Msg ;Display message about write parm rec MOV AH,09H ;DOS display string function INT 21H MOV AH,40h ;DOS WRITE function code MOV BX,PARM_Handle ;Handle for parm_file MOV CX,45 ;Write 45 bytes to disk MOV DX,OFFSET PARM_buffer ;Data to write to disk INT 21h ;Do the I/O JNC PARM_write_OK ;If I/O was successful ;Else the we had an I/O error JMP Unrecoverable_IO_Error PARM_write_OK: ;Write of Parm_file worked ok MOV AH,3Eh ;DOS close file function code INT 21h ;Close the file RET ;---------------------------------------------------; ; W R I T E B O O T S E C T O R (F I L E) ; ;---------------------------------------------------; ;Write a reloadable version of the boot sector to ; ;DISK. This is done during intialization. ; ;---------------------------------------------------; Write_Boot_Sector: MOV DX,offset BootW_MSG ;Display msg about writing boot file MOV AH,09H ;DOS display string function INT 21H MOV AH,3Ch ;DOS create file function MOV DX,Offset Boot_File_Name XOR CX,CX ;Set CX (file attribute=normal) = 0 INT 21h JNC Create_boot_OK ;IF all went OK then return Boot_Write_Error: JMP Unrecoverable_IO_Error Create_Boot_OK: MOV BX,AX ;Handle for Boot sector file MOV AH,40h ;DOS WRITE function code MOV CX,69 ;Length of reload sector prefix ADD CX,Sector_Size ;Write 1 sector + 69 bytes MOV DX,OFFSET Write_buffer ;Data to write to disk INT 21h ;Do the I/O JNC Boot_write_OK ;If I/O was successful ;Else the we had an I/O error JMP Unrecoverable_IO_Error Boot_write_OK: ;Write of Parm_file worked ok MOV AH,3Eh ;DOS close file function code INT 21h ;Close the file RET ;---------------------------------------------------; ; W R I T E P A R T S E C T O R (F I L E) ; ;---------------------------------------------------; ;Write a reloadable version of the partition sector ; ;to disk. This is done during initialize processing.; ;---------------------------------------------------; Write_Part_Sector: MOV DX,offset PartW_MSG ;Display msg about writing Part file MOV AH,09H ;DOS display string function INT 21H MOV AH,3Ch ;DOS create file function MOV DX,Offset Part_File_Name XOR CX,CX ;Set CX (file attribute=normal) = 0 INT 21h JNC Create_Part_OK ;IF all went OK then return Part_Write_Error: JMP Unrecoverable_IO_Error Create_Part_OK: MOV BX,AX ;Handle for Part sector file MOV AH,40h ;DOS WRITE function code MOV CX,69 ;Length of reload sector prefix ADD CX,Sector_Size ;Write 1 sector + 69 bytes to disk MOV DX,OFFSET Write_buffer ;Data to write to disk INT 21h ;Do the I/O JNC Part_write_OK ;If I/O was successful ;Else the we had an I/O error JMP Unrecoverable_IO_Error Part_write_OK: ;Write of Parm_file worked ok MOV AH,3Eh ;DOS close file function code INT 21h ;Close the file RET ;---------------------------------------------------; ; V A L I D A T E P A R M F I L E ; ;---------------------------------------------------; ;Check that the parameter file itself has not been ; ;corrupted in some way. ; ;---------------------------------------------------; Validate_Parm_File: ; make sure its a valid parm file ; --------- Calculate cryptographic XOR sum for the PARM file --------------- MOV SI,offset PARM_BUFFER ;Point SI to buffer containing sector MOV CX,41 ;Check 1st 41 characters in buffer CALL Calc_Sums ;Calculate CHK and XOR sums ; ----------------------------------------------------------------------------- ; Compare the calculated with the recorded check/XOR sums CMP PARM_XOR_Sum,DX ;Compare XOR sum JNE Bad_Parm_File ;If parm file corrupted.. CMP PARM_CHK_SUM,DI ;Compare CHK sum JNE Bad_Parm_File ;If parm file corrupted.. RET ;Otherwise return..all is well so far Bad_Parm_file: MOV DX,offset BadP_MSG ;Explain that Parm file is corrupted MOV AH,09H ;DOS display string function INT 21H CALL Send_Beep ;Wake up user! CALL Wait_For_Key ;Beep and force user to hit a key MOV AX,4C20h ; terminate with 32 DOS ERRORLEVEL INT 21h SUBTTL General Purpose subroutines PAGE ;******************************************************************************; ;** General purpose subroutines follow **; ;******************************************************************************; SUBTTL General purpose subroutines PAGE ;---------------------------------------------------; ; C A L C S U M S - Calculate XOR + CHK sums ; ;---------------------------------------------------; ; INPUT: SI = pointer to file BUFFER to scan ; ; CX = # of characters to read ; ; ; ;Register conventions: ; ; ; ; AL - Each new character read into this register ; ; CX - number of chars read in -decreasing counter ; ; DI - Contains checksum for this file ; ; DX - XOR sum ; ; SI - index pointing into file BUFFER ; ; --------------------------------------------------; Calc_Sums: XOR DX,DX ;Zero XOR sum XOR DI,DI ;Zero CHK sum XOR AH,AH ;Zero upper part of AX for addition ; Innermost char loop - keep this fast! NEXT_CHAR: LODSB ;Get char into AL XOR DL,AL ;cumulative XOR into DX ROL DX,1 ;Keep shifting to XOR sum to left ADD DI,AX ;cumulative check sum LOOP NEXT_CHAR ;CONTINUE SCANNING CHARS UNTIL EOB RET ;All done calculating sums! ;---------------------------------------------------; ; D I S P L A Y M A X H E L P - Display adv help; ;---------------------------------------------------; ; 1) Clear the screen ; ; 2) Send message pointed to by DS:DX ; ; 3) Beep and wait for any key press ; ; --------------------------------------------------; Display_Max_Help: CALL Clear_Screen ;Clear screen and set cursor to top MOV AH,09H ;DOS display string function INT 21H CALL Pos_Cursor_Line25 ;Go to last line of screen CALL Wait_for_key ;Wait for key press RET ;---------------------------------------------------; ; C L E A R S C R E E N - Erase contents of screen; ; and position cursor at top of screen. Maintain ; ; user's current screen attributes (colors). ; ; ; ; Entry: Current_Screen_atr contains current screen ; ; attribute. (Set by routine: Get_Screen_Atr); ;---------------------------------------------------; Clear_Screen: PUSH BP ;Save registers PUSH DX ; Clear the screen using the BIOS scroll screen function MOV AX,0600h ;06=scroll function. ;00=lines to scroll = clear screen MOV BH,Current_Screen_Atr ;Attribute byte to fill screen MOV CX,00 ;upper left corner is (0,0) = (y,x) MOV DX,184Fh ;Lower rt corner=(y,x)=(24,79) INT 10h ;Call BIOS video services ; Position cursor to line 00 column 00 MOV AH,02 ;BIOS int 10h set cursor position func XOR BH,BH ;Set page to zero MOV DX,0000h ;Set cusor to row 00 and column 00 INT 10h ;BIOS video services POP DX POP BP ;Restore registers RET ;---------------------------------------------------; ; S E N D B E E P ; ;---------------------------------------------------; ; Cause the PC to put out a BEEP sound. ; ;This is used to alert user to an error condition. ; ;---------------------------------------------------; Send_Beep: PUSH BP ;Save all vulnarable registers PUSH DX ; Produce a beep to alert the user: (use BIOS TTY func to write an ASCII BELL) MOV AX,0E07H ;BIOS func (0Eh) to write (07H) beep XOR BH,BH ;Select page zero for output INT 10H ;BIOS video function (0Eh=write char) POP DX POP BP ;Restore registers RET ;---------------------------------------------------; ; G E T C U R R E N T S C R E E N A T R ribute; ;---------------------------------------------------; ;Determine forground and background colors in use ; ;and save for use by other BIOS video functions. ; ; Save it in: "Current_Screen_Atr" ; ;---------------------------------------------------; Get_Current_Screen_Atr: PUSH BP ;Save all vulnarable registers PUSH DX ;Find out what attribute is being used for display MOV AH,08h ;read attrib + char function INT 10h ;Call BIOS video services MOV Current_Screen_Atr,AH ;Save AH=attribute byte POP DX POP BP ;Restore registers RET ;---------------------------------------------------; ; P O S C U R S O R on L I N E 2 5 ; ;---------------------------------------------------; ;Move cursor position to line 25 (BIOS line 24) ; ;the last line on the screen. . ; ;---------------------------------------------------; Pos_Cursor_Line25: PUSH BP ;Save all vulnarable registers PUSH DX ; Position cursor to line 25 and column 01: (TO BIOS col 00 + row 24) MOV AH,02 ;BIOS int 10h set cursor position func XOR BH,BH ;Set page to zero MOV DX,1800h ;DH = row 24; DL = col 00 INT 10h ;BIOS video services POP DX POP BP ;Restore registers RET ;---------------------------------------------------; ; W A I T F O R K E Y ; ;---------------------------------------------------; ; 1) Put out message to hit any key on current line.; ; 2) Wait for any key press ; ; 3) Erase message using current screen attribute ; ; 4) Position currsor back at start of current line.; ; --------------------------------------------------; Wait_For_Key: PUSH BP ;Save all corrupted registers PUSH DX ;Find out what line the cursor is on MOV AH,03h ;Read cursor position function INT 10h ;BIOS video services PUSH DX ;DH contains row (line #) Save it! ; Position cursor to current line + column 28: (TO BIOS row 27) MOV AH,02 ;BIOS int 10h set cursor position func XOR BH,BH ;Set page to zero ;DH contains current row MOV DL,1Bh ;Set cusor current row and col 27 INT 10h ;BIOS video services ; Put -Hit any key- message out with inverse video attribute type on ; XOR BH,BH ;Set page to zero (BH is still 0) MOV BL,0F0h ;Inverse video attribute MOV CX,1 ;Character count MOV SI,offset Hit_Key_Msg ;The hit-any-key message Display_next_video_char: MOV AH,09H ;BIOS int 10h write attrib + char func LODSB ;Get next character for output PUSH SI ;Save SI (int 10h may corrupt it) INT 10h ;Put character and attribute out INC DX ;Advance cursor position MOV AH,02 ;Adv cursor function INT 10h ; advance the cursor (BIOS) POP SI ;Restore saved SI CMP SI,offset Hit_key_Msg_end ;are we at end of message? JB Display_next_video_char ; If not get next char for display ; Else, wait for key press by user ; Wait for user to hit any key XOR AX,AX INT 16h ;Wait for user to hit a key ; Erase HIT ANY KEY message POP DX ;DH=current line number MOV BH,Current_Screen_Atr ;AH=user's screen attribute MOV AH,06h ;INIT window function XOR AL,AL ;Zero AL to clear window MOV CH,DH ;Current row (y coor upr lft) MOV CL,00 ;Start in first char position MOV DL,79 ;Last char pos - blank entire line INT 10h ;Blank out line ; Position cursor to start of blanked line MOV AH,02 ;BIOS int 10h set cursor position func XOR DL,DL ;DH=cur line, DL=0: first char pos XOR BX,BX ;Use video page zero INT 10h ;BIOS video services POP DX POP BP RET ;Return to caller ; ----------------------------------------------------------------------------; ; Initialization code - parse parms + put out msgs ; ; ----------------------------------------------------------------------------; Parse_parms: ;Parse input parameters MOV AH,30h ;Check DOS version INT 21h ; Ask DOS: "who are you?" OR AL,AL ;Check if before DOS 2.x (AL=0) JNE DOS_is_OK ;If good DOS vers, then continue MOV DX, OFFSET Bad_DOS_Msg ; ELSE Send MSG that MOV AH,09h ; DOS version is too low. INT 21h INT 20h ; Old style DOS terminate interupt DOS_is_OK: MOV DOS_Version,AL ;Save major DOS version number (0-4) MOV SI,80H ;Parameter area in PSP MOV CL,[SI] ;Get # of chars in input parm XOR CH,CH ;CLEAR UPPER BYTE OF CHR COUNT OR CL,CL ;CHECK FOR 0 CHARS (NO INPUT) MOV DX, OFFSET Explanation ;Give user full explanation of prgm JNZ Continue_parse ;If some parameters keep going JMP Help_display ; Else, give user some help info Continue_parse: INC SI ;POINT TO FIRST CHARACTER CLD ;FORWARD DIRECTION DEL_SPACES: LODSB ;Get byte at DS:SI and inc SI CMP AL,'/' ;Is it a "/" JE Scan_for_parms ;If so, we have a parameter CMP AL,' ' ;Is it a space? JNE Scan_Filespec ;If not we have a filespec LOOP DEL_SPACES ;CONT CHECKING UNTIL LAST CHAR JMP Help_Display ;---------------------------------------------------------------------------; ; Conventions for command line parsing: ; ; SI points to next char to be checked in the parm field at DS:80 ; ; CX is count of characters left to be scanned ; ;---------------------------------------------------------------------------; Scan_Filespec: ;Parse user override to parameter file ;----------------------------------------; ; Parse filespec + xfer to Parm_FIle_Name; ;----------------------------------------; DEC SI ;point back to 1ST letter of filespec MOV DI, offset Parm_File_Name ;prep to transfer file name to msg Scan_To_File_Spec_End: ; start scanning the file specification and transfer into output field LODSB ;Get next char of file spec CMP AL,' ' ;check valid separator character JBE file_spec_end_found CMP AL,'/' ;check for valid separator JE file_spec_end_found STOSB ;Store char as part of User_file_spec LOOP Scan_To_File_Spec_End JMP Help_Display ;There must be at least on /x parm ;So give user HELP with CHKBOOT File_Spec_End_Found: ;SI = next char loc after filespec PUSH AX ;Save last char examined MOV AL,00 ;Zero terminate the filespec STOSB ; combination as a single word POP AX ;Restore last character examined Scan_for_parms: CMP CX,01 ;Check if we out of chars to scan JA Parm_Scan ;If some are left, check parameters JMP Help_display ;If so, user needs HELP Check_parm_chars_left: ;Check if enough chars left for a parm CMP CX,01 ;Check if we out of chars to scan JA Parm_Scan ; if not continue chcking for /parms RET ; If so, return Parm_Scan: ;Check for presence of a /_ parm CMP AL,'/' ;check for "/" parm character JE Parm_found CMP AL,' ' ;check for blanks JNE Unrecog_parm ;If other than blank its illegal... LODSB ;Keep checking next character LOOP Parm_Scan RET ;All done Parm_Found: ;Check if parm is valid DEC CX ;Adjust chars remaining counter JCXZ Unrecog_parm ;IF no chars left then parm is invalid LODSB ;Get next char DEC CX ;Adjust chars remaining counter CMP AL,'2' ;Is it the Initialize parm? JE Two_parm ;2 parm detected.. AND AL,5Fh ;Capitalize char CMP AL,'P' ;Is it Partition table parm? JE P_parm ;P parameter detected CMP AL,'B' ;Is it the Boot record parm? JE B_parm ;I parm detected.. CMP AL,'I' ;Is it the Initialize parm? JE I_parm ;I parm detected.. CMP AL,'H' ;Is it the Initialize parm? JE H_parm ;I parm detected.. Unrecog_parm: ; an illegal paramter: MOV DX, offset Bad_Parm_Msg ;indicate illegal parm was found MOV AH,09H ;DOS display string function INT 21H JMP SHORT ERR_Exit ;terminate with error level set Illegal_P_2_Parms: ;User has entered both /P + /2 MOV DX, offset Bad_P_2_Msg ;indicate use of /P+/2 found MOV AH,09H ;DOS display string function INT 21H JMP SHORT ERR_Exit ;terminate with error level set P_parm: CMP Partition2_wanted,'Y' ;Has user already selected /2 JE Illegal_P_2_Parms ; If so, give error message MOV Partition_wanted,'Y' ;Indicate user wants partition table LODSB ;Keep checking next character JMP SHORT Check_Parm_chars_left ;Check for additional parms B_parm: MOV Boot_wanted,'Y' ;Indicate user wants boot record LODSB ;Keep checking next character JMP SHORT Check_Parm_chars_left ;Check for additional parms I_parm: MOV Initialize_mode,'Y' ;Force intialization mode LODSB ;Keep checking next character JMP SHORT Check_Parm_chars_left ;Check for additional parms Two_parm: ;/2 parm (read partition on 2nd disk) CMP Partition_wanted,'Y' ;Has user already selected /P JE Illegal_P_2_Parms ; If so, give error message MOV Partition_wanted,'Y' ;Indicate user wants a partition table MOV Partition2_wanted,'Y' ;Indicate user wants 2nd partit table INC Drive_number ;Read drive number 81 (2nd hard drive) LODSB ;Keep checking next character JMP SHORT Check_Parm_chars_left ;Check for additional parms H_parm: ;Handle HELP request CALL Get_Current_Screen_Atr ;Use user's choice of screen colors MOV DX, offset Max_Help1 ;Give user detailed help information CALL Display_Max_Help ;Clear screen/Displ HELP/wait for key MOV DX, offset Max_Help2 ;Give user Help page 2 CALL Display_Max_Help MOV DX, offset Max_Help3 ;Help page 3 CALL Display_Max_Help CALL Clear_Screen JMP SHORT Syntax_msg_only ;Give syntax summary Err_Exit: CALL Send_Beep ;Alert user to serious error! CALL Wait_For_Key ;Beep and force user to hit a key Syntax_msg_only: MOV DX, offset Syntax_Msg ;show user correct syntax Help_Display: MOV AH,09H ;DOS display string function INT 21H MOV AX,4C80h ; terminate with 128 DOS ERRORLEVEL INT 21h SUBTTL Definition of Data structures PAGE ;******************************************************************************; ;** Definition of Data areas follow **; ;******************************************************************************; Boot_wanted DB 'N' ;Read DOS boot sector Y or N? partition_wanted DB 'N' ;Read any Partition sector Y or N? partition2_wanted DB 'N' ;Read part on 2nd disk Y or N? Initialize_Mode DB 'N' ;Read DOS boot sector Y or N? Current_Screen_Atr DB 07 ;Screen attribute to use for BIOS I/O DOS_Version DB 00 ;Major version of DOS used (0 - 4) Sector_Size DW 00 ;Number of bytes per sector INT25_Parms LABEL BYTE ;DOS 4.0 INT25/26 parameter block Sector_Number DD 00 ;DOS logical sector number to read Sector_Count DW 01 ;Read 1 sector Buffer_Offset DW OFFSET Buffer ;Buffer address - offset Buffer_Segment DW 0 ; segment - set at run time Missing_Msg DB 'Parameter file is missing. Creating a new copy...',CR,LF,'$' PW_MSG DB 'Writing the parameter file.',CR,LF,'$' BootW_MSG DB 'Writing "@@BOOT.SCT."',CR,LF,'$' PartW_MSG DB 'Writing "@@PARTIT.SCT".',CR,LF,'$' Init_Msg DB 'Executing in initialization mode. New files will be ' DB 'created. (.PRM + .SCT)',CR,LF,'$' IO_ERR_Msg DB 'I/O error',CR,LF,'$' No_hardDisk_MSG DB 'Partition sector not processed. Hard disk not found.' DB CR,LF,'$' BAD_Sector_Msg DB 'modification (system corruption) detected.',CR,LF,'$' BadP_MSG DB 'Parameter file has been corrupted.',CR,LF,'$' DB CR,LF,'$' Part_Msg DB 'Partition sector ','$' Boot_Msg DB 'DOS Boot sector ','$' OK_Msg DB 'OK.',CR,LF,'$' Parm_File_name DB 'CHKBOOT.PRM' ;ASCIIZ string of parameter file name DB 64 DUP (0) ;Include space to handle path on file Boot_File_name DB '@@BOOT.SCT',00 ;ASCIIZ string of boot sector file Part_File_name DB '@@PARTIT.SCT',00 ;ASCIIZ string of partition file Drive_number DW 80h ;Drive number for BIOS hard disk read Parm_handle DW 00h ;File handle for parameter file Parm_Buffer Label byte Parm_header DB 'CHKBOOT-Author: Wolfgang Stiller:' Boot_XOR_Sum DW 0000h ;Boot record exclusive or sum Boot_CHK_Sum DW 0000h ;Boot record check sum Part_XOR_Sum DW 0000h ;Partition record exclusive or sum Part_CHK_Sum DW 0000h ;Partition record check sum PARM_XOR_Sum DW 0000h ;Validity check for PARM_file itself PARM_CHK_Sum DW 0000h ;Validity check for PARM_file itself Hit_Key_MSG DB '-Hit any key-' Hit_Key_MSG_end EQU $ Explanation LABEL BYTE DB 'CHKBOOT will check the DOS boot record and/or the partition sector for ' DB 'any ',CR,LF DB 'changes by using information recorded on the parameter file. On first' DB CR,LF DB 'execution, or with the "/I" parameter, CHKBOOT writes cryptographic ' DB 'check',CR,LF DB 'values to the parameter file and creates reload files for the boot ' DB 'and',CR,LF DB 'partition sectors. All files written contain self check information.' DB CR,LF,LF Syntax_Msg LABEL BYTE DB 'Syntax is: CHKBOOT [filespec] [/B] [/H] [/I] [/P] [/2]',CR,LF DB '"filespec" is optional file specification for the parameter file. If not' DB CR,LF DB ' specified, "CHKBOOT.PRM" will be used as the parameter file.' DB CR,LF DB ' "/H" Presents extensive detailed Help information.',CR,LF DB ' "/B" Checks boot record on current DOS disk for any changes.',CR,LF DB ' "/P" Checks partition sector on first physical hard disk for any ' DB 'changes.',CR,LF DB ' "/2" Checks partition sector on second physical hard disk.' DB CR,LF DB ' /P and /2 may not be specified together.' DB CR,LF DB ' "/I" Force initialization. Attempts read of current boot sector and ' DB 'partition',CR,LF DB ' sector on 1st hard drive (Include /2 for 2nd partition sector). ' DB 'CHKBOOT',CR,LF DB ' then writes the parameter file so that any changes to these ' DB 'sectors can',CR,LF DB ' be detected on subsequent executions. The boot and partition ' DB 'sectors are',CR,LF DB ' copied to files: "@@BOOT.SCT" and "@@PARTIT.SCT" for "LODboot" ' DB 'reload.',CR,LF Header_msg LABEL BYTE DB UPLT_Corner,76 DUP(Horizontal),UPRT_Corner,CR,LF DB vertical," CHKBOOT 1.0 þ PCDATA TOOLKIT Copyright (c) 1990 Ziff " DB "Communications Co. ",vertical,CR,LF DB Vertical," PC Magazine þ Wolfgang Stiller " DB " ",vertical,CR,LF DB LWLT_Corner,76 DUP(Horizontal),LWRT_Corner,CR,LF,'$' Write_Buffer DB 'LODboot reload file. Copy me to a floppy.' DB 'By Wolfgang Stiller',CR,LF DW 0FFFFh ;Special boot/partition indicator SCT_TYPE DB 0FFh ;Indicate if this is boot or part rec ; FF=Boot and 55=Partition sector SCT_CHK DW 00h ;CHK SUM(boot when used for parm file SCT_XOR DW 00h ;XOR SUM Buffer label byte ;All storage + code following is in ; the input file buffer. Bad_P_2_Msg DB '***SORRY***, /P may not be used with /2.',cr,lf,lf,'$' Bad_Parm_Msg DB 'Unrecognized parameter detected.',cr,lf,'$' Bad_DOS_MSG DB 'DOS 2.x or higher required.',CR,LF,'$' Non_Std_Msg DB 'Note, sectors on this disk are not 512 bytes.',CR,LF,'$' Max_Help1 DB 'The most difficult to detect type of damage (such as virus ' DB 'infection) is',CR,LF DB 'corruption of either your DOS boot sector or the partition sector. ' DB 'CHKBOOT',CR,LF DB 'will detect such damage if it happens, and give you the means to fix it' DB CR,LF DB 'with program LODboot.' DB CR,LF,LF DB 'What is a boot sector?' DB CR,LF DB 'The boot sector is sector 0 on a bootable DOS disk(ette). This sector ' DB 'contains',CR,LF DB 'the initial program executed when DOS is first started or booted by ' DB 'the ',CR,LF DB 'CNTL/ALT/DEL key combination. If this sector is damaged, you will have' DB CR,LF DB 'an unreliable or non-functioning operating system.' DB CR,LF,LF DB 'What is a partition sector (AKA: partition table)?' DB CR,LF DB 'If you have a hard (fixed) disk, each physical disk drive can be ' DB 'partitioned',CR,LF DB 'into multiple logical disks. A table on the first sector of the disk ' DB 'contains',CR,LF DB 'information on how the disk is partitioned. If the hard disk is ' DB 'bootable, then',CR,LF DB 'the partition sector also contains a program that loads and executes ' DB 'the DOS',CR,LF DB 'boot sector. If the partition sector is damaged, your hard disk ' DB 'may be unusable.$' Max_Help2 DB 'What does CHKBOOT do?' DB CR,LF,LF DB '1)During initialization, it will read the boot record on ' DB 'the current disk and',CR,LF DB ' attempt to read the partition record on the first hard disk (' DB 'or the second',CR,LF DB ' hard disk if "/2" is specified). Copies of these sectors will ' DB 'be written to',CR,LF DB ' files: @@BOOT.SCT and @@PARTIT.SCT. CHKBOOT will use 2 ' DB 'different algorithms',CR,LF DB ' to compute 32 bit cryptographic check signatures which uniquely ' DB CR,LF DB ' characterize each sector. These cryptographic signatures will ' DB 'be further',CR,LF DB ' encrypted and recorded on the parameter file.' DB CR,LF,LF DB '2)In normal use, CHKBOOT will read the parameter file and verify ' DB 'its integrity.',CR,LF DB ' It will then read the boot and/or the partition sectors. ' DB 'The cryptographic',CR,LF DB ' signatures will be calculated and compared with information ' DB 'stored on the',CR,LF DB ' parameter file. If a change to the boot or partition sectors ' DB 'is detected,',CR,LF DB ' the user will be notified.' DB '$' Max_Help3 DB 'How do you use CHKBOOT?' DB CR,LF,LF DB '1) Enter "CHKBOOT /I", in the root directory on any disks from ' DB 'which you boot',CR,LF DB ' your PC. This forces initialization of the parameter file ' DB '("CHKBOOT.PRM")',CR,LF DB ' and creates copies of the boot and partition sectors. If you ' DB 'boot from your',CR,LF DB ' second hard disk, enter: "CHKBOOT /I/2".' DB CR,LF,LF DB '2) Create a bootable floppy (FORMAT A:/S), then copy ' DB '@@BOOT.SCT, @@PARTIT.SCT,',CR,LF DB ' CHKBOOT.PRM, CHKBOOT.COM and LODBOOT.COM to it.',CR,LF,LF DB '3) Modify your AUTOEXEC.BAT file to include:' DB CR,LF DB ' "CHKBOOT /B" - for floppy only systems or' DB CR,LF DB ' "CHKBOOT /B/P" for systems where you boot from the first ' DB 'hard drive or',CR,LF DB ' "CHKBOOT /B/2" for systems where you boot from hard drive #2.' DB CR,LF DB ' If any changes are detected, CHKBOOT will beep, display a ' DB 'message and wait',CR,LF DB ' for a key press. Program LODboot can be used to restore.' DB CR,LF,LF DB '4) Checking in the AUTOEXEC file may not be effective if a ' DB 'virus is already in',CR,LF DB ' control, so also periodically issue the above command ' DB 'after booting from',CR,LF DB ' the floppy created in step 2 above. For example, on the disk' DB ' being checked,' DB CR,LF DB ' type:',CR,LF DB ' "a:CHKBOOT a:CHKBOOT.PRM/B/P"',CR,LF DB ' where "a:" is the floppy drive with the .PRM file.' DB '$' CSEG EndS END CHKBOOT