Materials: Working complete PC Blank Diskette Student Diskette, "New Boot A Ver 2.0+" Student CD-ROM, "Room 6359" Objectives: The student will become familiar with how to develop a complex batch file, The student will learn how to build a batch file that can detect missing or corrupt files. Competency: The student will understand the nature and function of real mode batch files and batch file programming. In this exercise the student will develop a powerful set of batch files that can scan the entire Windows folder looking for missing or corrupted Windows kernel files and therefore once found be able to replace them and get Windows to boot up again. |
Use Ghost to image the system with Windows 98. Boot to Command Prompt Only and change into the C:\WINDOWS\SYSTEM and do the following:
C:\WINDOWS\SYSTEM>copy msgsrv32.exe msgsrv32.bak 1 file(s) copied. C:\WINDOWS\SYSTEM>ren msgsrv32.exe msgsrv32.ex! C:\WINDOWS\SYSTEM>debug msgsrv32.ex! -f 100 110 0 -w Writing 2E90 bytes -q C:\WINDOWS\SYSTEM>ren msgsrv32.ex! msgsrv32.exe C:\WINDOWS\SYSTEM>_
At this point a core component of Windows has been corrupted. Launch Windows (by typing WIN[Enter]) and the system will respond with an infamous "Blue Screen of Death":
Now that the system is trashed, a batch file will be developed that can check all system files by extracting the originals from the CABs and then it will perform binary comparisons between the originals from the CABs and the files that are currently part of the running operating system. Any discrepancies found would indicate a corrupted file. Some files get renamed during the installation and some files do not exist in the CABs and some do get modified by the Windows 98 installation. By accounting for all of these issues, if a file still slips through as changed then it would certainly be the strongest possible cause of the blue screen and would be replaced.
First the batch file will have to be able list of all of the files in the operating system installation folder. The batch file does not have to check text files since the primary assumption is corrupted code. Therefore it will have to list only machine language files from the WINDOWS folder. Then it will have to extract these from the CABs and then finally it will have to perform the binary file comparison between the fresh one extracted from the CABs and the original copy on the hard drive. The batch file would then have to report any discrepancies.
To make the batch file universal, it should be made on a bootable diskette. The image of which can be burned into a bootable CD-ROM as well. Copy CHOICE.COM, FC.EXE, FIND.EXE, HIMEM.SYS, SMARTDRV.EXE, OAKCDROM.SYS, MSCDEX.EXE and XMSDSK.EXE to the floppy. Setup the floppy to launch all drivers and an 8MB ramdrive and an 8MB smartdrv buffer: CONFIG.SYS:
device=himem.sys device=oakcdrom.sys /d:CD01AUTOEXEC.BAT:
mscdex.exe /d:CD01 /L:Q xmsdsk 8192 K: /y /t smartdrv 8192 C+ set TMP=K:\ set TEMP=K:\ path=K:\ copy . K:\
Now the floppy can be used to access a Windows 98 OEM CD-ROM to perform the operation. The batch file will take two parameters: the location of the windows %systemroot% folder and the location of the installation CABs. Open EDIT.COM or Notepad and start the batch file with these lines:
@echo off rem check for passed params: rem param1 = Windows folder rem param2 = Source CABs folder if %1z==z goto help if %2z==z goto help rem at this point the params will be checked for validity if not exist %1\WIN.COM goto help2 if not exist %2\BASE4.CAB goto help2 rem at this point the folders exist so proceed rem set environmental variables SET WINDIR=%1 SET CABDIR=%2 rem the following is needed to initialize the variable to nothing on a second run SET CURRDIR= rem create the working folders on the RAM drive MD K:\TEMP MD K:\CABS MD K:\RPTS
Now for the working code. The batch file must change into the Windows directory and process every EXE by copying it to a temporary folder, then extract the original from the CABs then do the binary file comparison and then append a report file, then do the next task. The tasks are complicated enough that the best course of action in this case is to call another batch file that will handle this series of jobs. The other job handler looks like this:
@echo off rem Check for VMM32.VXD which can crash the commandline redirection and is known rem to be different from the one in the CABs anyway if %1z==VMM32.VXDz goto avoid echo Testing %WINDIR%%CURRDIR%\%1... K: cd \CABS extract /a %CABDIR%\BASE4.CAB %1 | find /c /i "no matching" | choice /n /c:01 > nul if errorlevel 2 goto notincab rem if it reaches here then the file was in the CABs copy %WINDIR%%CURRDIR%\%1 \TEMP > nul fc /b \TEMP\%1 %1 | find /c /i "no differences" | choice /n /c:01 > nul if errorlevel 2 goto end rem if it reaches here then the file is different echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\DIFF.RPT goto end :notincab echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\NOTINCAB.RPT :end if exist %1 del %1 if exist \TEMP\%1 del \TEMP\%1 :avoid C: cd %windir%%currdir%
Save this file as JOB.BAT on the floppy. Now the loop operation can call this batch file to work on each machine language file one at a time looking for a corrupt file.
Back in the original batch file add this code:
@echo off rem check for passed params: rem param1 = Windows folder rem param2 = Source CABs folder if %1z==z goto help if %2z==z goto help rem at this point the params will be checked for validity if not exist %1\WIN.COM goto help2 if not exist %2\BASE4.CAB goto help2 rem at this point the folders exist so proceed rem set environmental variables SET WINDIR=%1 SET CABDIR=%2 rem the following is needed to initialize the variable to nothing on a second run SET CURRDIR= rem create the working folders on the RAM drive MD K:\TEMP MD K:\CABS MD K:\RPTS REM ADD THE FOLLOWING: C: cd %windir% echo Checking executable OS components in %windir% for %%I in (*.EXE) do call job %%I for %%I in (*.DLL) do call job %%I for %%I in (*.COM) do call job %%I for %%I in (*.SYS) do call job %%I for %%I in (*.386) do call job %%I for %%I in (*.VXD) do call job %%I for %%I in (*.PDR) do call job %%I for %%I in (*.DRV) do call job %%I echo Checking executable OS components in %windir%\SYSTEM cd %windir%\system set CURRDIR=\SYSTEM for %%I in (*.EXE) do call job %%I for %%I in (*.DLL) do call job %%I for %%I in (*.COM) do call job %%I for %%I in (*.SYS) do call job %%I for %%I in (*.386) do call job %%I for %%I in (*.VXD) do call job %%I for %%I in (*.PDR) do call job %%I for %%I in (*.DRV) do call job %%I echo Checking executable OS components in %windir%\SYSTEM32 cd %windir%\system32 set CURRDIR=\SYSTEM32 for %%I in (*.EXE) do call job %%I for %%I in (*.DLL) do call job %%I for %%I in (*.COM) do call job %%I for %%I in (*.SYS) do call job %%I for %%I in (*.386) do call job %%I for %%I in (*.VXD) do call job %%I for %%I in (*.PDR) do call job %%I for %%I in (*.DRV) do call job %%I echo Checking executable OS components in %windir%\SYSTEM\IOSUBSYS cd %windir%\system\iosubsys set CURRDIR=\SYSTEM\IOSUBSYS for %%I in (*.EXE) do call job %%I for %%I in (*.DLL) do call job %%I for %%I in (*.COM) do call job %%I for %%I in (*.SYS) do call job %%I for %%I in (*.386) do call job %%I for %%I in (*.VXD) do call job %%I for %%I in (*.PDR) do call job %%I for %%I in (*.DRV) do call job %%I echo Checking executable OS components in %windir%\SYSTEM\VMM32 cd %windir%\system\vmm32 set CURRDIR=\SYSTEM\VMM32 for %%I in (*.EXE) do call job %%I for %%I in (*.DLL) do call job %%I for %%I in (*.COM) do call job %%I for %%I in (*.SYS) do call job %%I for %%I in (*.386) do call job %%I for %%I in (*.VXD) do call job %%I for %%I in (*.PDR) do call job %%I for %%I in (*.DRV) do call job %%I echo Operation complete... K: pause echo Files in which differences were detected: type \RPTS\DIFF.RPT | more pause echo Files not found in the CABs: type \RPTS\NOTINCAB.RPT | more goto end :help echo SYNTAX: echo. echo FILECHK WINDIR CABDIR echo Where: echo WINDIR location of Windows; must be a full absolute path echo CABDIR location of the CABs; must be a full absolute path echo. echo EXAMPLE: echo. echo FILECHK C:\WINDOWS D:\WIN98 goto end :help2 echo Either %1\WIN.COM or %2\BASE4.CAB is missing. :end
Save the batch file to the floppy and be sure that it is bootable and all of the above components are on the floppy as well. Boot to the floppy and then run FILECHK.BAT from the commandline. Even with smartdrv and a ram drive extract.exe grinds through the CABs very slowly and the batch file can take a very long time to process all of the files. When it is finished it will pause the process and then display the report files on screen.
This file checker does not take into account service packs, files replaced by software, or Microsoft patches which all change the original files which will report differences. Over time these can range into the hundreds. By the way these "legitimate" changes can indeed be the cause of the blue screen!
After running the file on the test system the contents of DIFF.RPT appear as follows:
C:\WINDOWS\SETVER.EXE C:\WINDOWS\SYSTEM\MSGSRV32.EXE C:\WINDOWS\SYSTEM\USER.EXE C:\WINDOWS\SYSTEM\MAPI32.DLL
Note that SETVER.EXE will always be different. It violates the #1 rule of good coding: it is a self-modifying program and stores the SETVER list within itself. MS saw the folly of their ways and never did this again. Programs save such information in *.INI files and then later the Registry. MAPI32.DLL is another mysterious file that ends up different. USER.EXE is a concern and of course MSGSRV32.EXE is the file that was damaged. Here is the list of files that are known to be modified from their originals in the CABs:
C:\WINDOWS\SETVER.EXE C:\WINDOWS\SYSTEM\VMM32.VXD C:\WINDOWS\SYSTEM\MAPI32.DLL
NOTE: This list is preliminary (incomplete) at this time.
Any file not in the CABs came from one of four possible places: 1) It is in the WIN98 folder uncompressed or 2) It was created by the installation routine like VMM32.VxD, 3) It is renamed during install and has a different name in the CABs, 4) It is a third party addition or a microsoft update (service pack, etc). JOB.BAT can be modified to account for the possibility that the file is in the CABs folder uncompressed:
@echo off
if %1z==VMM32.VXDz goto avoid
echo Testing %WINDIR%%CURRDIR%\%1...
K:
cd \CABS
extract /a %CABDIR%\BASE4.CAB %1 | find /c /i "no matching" | choice /n /c:01 > nul
if errorlevel 2 goto notincab
rem if it reaches here then the file was in the CABs
copy %WINDIR%%CURRDIR%\%1 \TEMP\%1 > nul
fc /b \TEMP\%1 %1 | find /c /i "no differences" | choice /n /c:01 > nul
if errorlevel 2 goto end
rem if it reaches here then the file is different
:diff
echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\DIFF.RPT
goto end
:notincab
if not exist %CABDIR%\%1 goto notncab2
copy %WINDIR%%CURRDIR%\%1 \TEMP\%1 > nul
copy %CABDIR%\%1 . > nul
fc /b \TEMP\%1 %1 | find /c /i "no differences" | choice /n /c:01 > nul
if errorlevel 2 goto end
rem gets here then it was in CABDIR but different
goto diff
:notncab2
echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\NOTINCAB.RPT
:end
if exist %1 del %1
if exist \TEMP\%1 del \TEMP\%1
:avoid
C:
cd %windir%%currdir%
You can add other files to the avoid process of JOB.BAT. Here is SETVER.EXE and MAPI32.DLL being avoided:
@echo off
if %1z==VMM32.VXDz goto avoid
if %1z==SETVER.EXEz goto avoid
if %1z==MAPI32.DLLz goto avoid
echo Testing %WINDIR%%CURRDIR%\%1...
K:
cd \CABS
extract /a %CABDIR%\BASE4.CAB %1 | find /c /i "no matching" | choice /n /c:01 > nul
if errorlevel 2 goto notincab
rem if it reaches here then the file was in the CABs
copy %WINDIR%%CURRDIR%\%1 \TEMP\%1 > nul
fc /b \TEMP\%1 %1 | find /c /i "no differences" | choice /n /c:01 > nul
if errorlevel 2 goto end
rem if it reaches here then the file is different
:diff
echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\DIFF.RPT
goto end
:notincab
if not exist %CABDIR%\%1 goto notncab2
copy %WINDIR%%CURRDIR%\%1 \TEMP\%1 > nul
copy %CABDIR%\%1 . > nul
fc /b \TEMP\%1 %1 | find /c /i "no differences" | choice /n /c:01 > nul
if errorlevel 2 goto end
rem gets here then it was in CABDIR but different
goto diff
:notncab2
echo %WINDIR%%CURRDIR%\%1 >> K:\RPTS\NOTINCAB.RPT
:end
if exist %1 del %1
if exist \TEMP\%1 del \TEMP\%1
:avoid
C:
cd %windir%%currdir%
All files that get listed in NOTINCAB.RPT at this point are either added to the system, created by setup, or have been renamed by setup. Here is the list of files that setup renames:
In the CABs | becomes this | On the HDD |
SHELL.NEW | SHELL.DLL | |
VER.NEW | VER.DLL |
NOTE: This list is preliminary (incomplete) at this time.
The AUTOEXEC.BAT automatically copies all files from the floppy to the root of the RAM drive and sets the PATH to point there. This allows both batch files and all executables to run from the much faster RAM drive than from the very slow floppy disk. The reports are also stored in the RPTS directory of the RAM drive. Files are copied from the hard drive to the RAM drive and they are decompressed from the CABs to the RAM drive, then the copy of the original and the newly decompressed files are compared on the RAM drive. All of this has been done to make the tools work as fast as possible with the caveat that if the file is corrupt and cannot be copied to the RAM drive, then the problem has possibly been found, but these tools will not record that event. The technician will have to record the file names that fail to copy AND use the [F]ail choice when prompted with the "Abort, Retry, Fail?" choices. Also if the batch files crash at any point then the reports will be lost, but since this all runs many times faster than keeping the reports on the floppy, the risk is worth it. Change to the K: drive and type: FILECHK C:\WINDOWS Q:\WIN98SE if working with the lab systems. The process takes about 2 hours on the lab systems which have rather old and slow non-UDMA hard drives.
Here is a file list from NOTINCAB.RPT run on a pristine installation of Windows 98 Second Edition with no other software installed:
WSOCK32.DLL CFGWIZ.DLL CFGWIZ32.EXE DINDI.DLL DLCNDI.DLL INFRARED.DLL ISSETUP.DLL MSTCP.DLL NDSWAN16.DLL NDSWAN32.DLL NETAPI.DLL NETDI.DLL NETOS.DLL NWNDS.DLL PPPNDI.DLL RNASETUP.DLL DSKMAINT.DLL COMMCTRL.DLL LZEXPAND.DLL MSPRINT.DLL MSPRINT2.DLL SYSDETMG.DLL SUCATREG.EXE SETUPX.DLL COMMDLG.DLL SHELL.DLL VER.DLL ICMFIL~1.DLL MSJETO~1.DLL MAPI32X.DLL HWINFOD.VXD
How to find a file that is "not in the CAB's"
This list will take a while to complete. In the meantime here is how to find the renamed files for yourself. The key is the file's size. It may not be unique because all of the components of Windows are aligned. However, here is how to search the CABs for a renamed file. First read NOTINCAB.RPT and choose one, in this example SHELL.DLL will be used. Now run DIR for the file to get its size:
C:\>dir shell.dll /s
Volume in drive C has no label
Volume Serial Number is 0630-1AE0
Directory of C:\WINDOWS\SYSTEM
SHELL DLL 126,704 01-07-98 8:11p
1 file(s) 126,704 bytes
Total files listed:
1 file(s) 126,704 bytes
0 dir(s) 1,698,824,192 bytes free
C:|>_
The file is 126,704 bytes in size. Now run extract so that it will display the contents of all of the CABs and PIPE the output through the FIND filter looking for this file size report text:
C:\>extract /a /d c:\win98\base4.cab | find "126,704"
04-23-1999 10:22:00p A--- 126,704 shell.new
C:\>_
And there it has been revealed that the file SHELL.DLL is stored in the CABs under the alias SHELL.NEW.
The modified file checker for the Windows NT Family will be included in a future module linked here.
Copyright©2000-2006 Brian Robinson ALL RIGHTS RESERVED