The Startup Axis
Not quite everything I know about the Windows 9x startup axis, seeing as there are some risk issues that don't seem to have been exploited by malware as yet. The system startup process is divided into six phases:
Power supply phase
BIOS phase
OS-independent boot phase
OS real-mode phase
OS Windows phase
Windows Logon
Program code in gray, settings files and entries in purple.
Note that this description outlines the normal Windows boot process, but several factors can cause a detour into DOS mode instead (except in the case of Windows Millennium, which simply falls over if Windows cannot run).
The power supply checks voltages for stability and ground for offset before powering up the system and asserting the Power Good signal so that the processor begins processing.
If there are problems at this level, e.g. there's a short circuit, wrongly-orientated IDE data cable, or a ground offset from something connected to the parallel port from a different power outlet, then the power supply should not proceed to power up the system.
This is when you see a system that passes mains to the monitor but is otherwise completely dead; no fan or hard drive activity, no keyboard LED responses. Usually, about the first sign of passing this point is when all three keyboard status LEDs flash briefly at the same time; that's probably the end of this phase in the boot process.
The system BIOS (Basic Input/Output System) is a set of OS-independent programs in ROM that configure the system, seek and boot an operating system (OS), and provide service routines that the OS may or may not use. The first of these BIOS tasks is the Power On Self Test (POST). This has its origins in the 286 era!
First, a scan is made of memory between 640k and 1M, looking for 55AA (hex) markers at the end of address blocks. If found, the BIOS detects this as an additional ROM and appears to pass control to it at this point (given that SVGA BIOS text messages are often the first characters to appear on screen). In addition to the graphic controller BIOS, there may be ROMs for LAN and hard drive controller cards present.
RAM is sized and perhaps a cursory test is done, and an equipment list is built from 286-era devices that are detected; keyboard, the first three parallel ports, the first four serial ports, the first two diskette drives and up to four IDE devices.
Settings held in CMOS memory may modify this behavior, e.g. suppress the diskette seek tests that were used to distinguish 40-track from 80-track floppy drives. Most generic systems contain programs within the BIOS that display CMOS Setup menus to control these settings, and it is around this point that the keyboard is checked to see if the user is attempting to summon this facility.
However, some "brand names" lack this ability - e.g. some Compaq systems store the CMOS Setup programs in a "special" hard disk partition, some Toshiba mini-notebooks rely on DOS programs to run the CMOS Setup facility and so on. This can complicate troubleshooting and the management of boot viruses.
Plug-n-Play binds together several "intelligent device" hardware standards such as PCI, PCMCIA etc. into a cohesive system. PnP devices that are not required to boot are supposed to stay inert until the PnP manager queries them for their preferred and alternate choice of hardware resources, and then sequentially assigns such resources and initializes each device.
A record of these assignments is held in Non-Volatile RAM, which may also be referred as PnP Configuration Data, ESCD, or other acronyms.
The PnP manager can be within the OS (PnP was first implemented in Windows 95), within the BIOS, or as a third layer of software called by a non-PnP OS (such as DOS or DOS mode).
Because different PnP managers can store their information slightly differently in NVRAM, it's often preferable to have only one active PnP manager, so many BIOSs have CMOS settings that default to "PnP OS Present", which effectively disables BIOS PnP and leaves PnP management to the OS. But that means PnP devices may not be available in pure DOS mode, as there's no built-in PnP manager there.
If PnP BIOS is active, this is where it happens. Often the very last on-screen message from the BIOS phase is something like "Updating ESCD..." which may or may not be followed by "Success!" on the same line. On systems that do not indicate success, there may appear to be a problem with this process should the next process fail before any messages are displayed - this has caused much digging in the wrong place.
Having finished POST, built an equipment list, and optionally done PnP management, the BIOS then seeks a boot device according to settings held in CMOS. Traditionally, the first boot device was either a LAN boot ROM or the first diskette drive, but now one can usually select other devices such as hard drives, CD-ROM, LS120 or Zip drives to boot first.
Best practice is to avoid booting from removable disks of any kind, and especially diskettes. This is because if a virus-infected disk is left in such a drive, an attempt to boot off it will provide the virus with an entry to the system. You should set A: to boot before C: only while doing troubleshooting, and not leave that boot order as a permanent setting.
If the boot device is a disk drive, the end of the first sector of that disk is checked for a 55AA hex boot signature, and if found, that sector is loaded into RAM and executed - thus ending the BIOS hardware phase of the boot process.
What the first sector of the boot disk does is entirely up to whoever programmed that code. In the case of hard drives, the sector is called the Master Boot Record and is expected to follow a particular pattern, regardless of what operating systems (OSs) are installed. In fact, the MBR is neutral territory; it belongs to no OS, and any OS may be expected to splat completely standard program code into it.
It is a foolish OS that puts OS-specific content here, with the expectation of ever seeing it again.
Here's what MBR code is expected to do...
Within the first sector of a bootable hard drive is a table of four entries that describe up to four partitions (address ranges) on the hard drive. Each starts with a type marker byte that uses the lowermost 7 bits to identify the OS and partition type. The most significant bit is set if the partition is to be booted, otherwise it is reset to indicate it is not to be booted. There should be only one partition marked as "active" in this way.
The MBR code is expected to look up the partition table, determine which partition is active (or generate an error), and find where that partition starts. Next, it's expected to pull the first sector of that partition into RAM and see if the last two bytes are a 55AA hex boot signature. If they are, it's assumed to be a valid boot sector and the code jumps to the start of that sector and executes from there - thus marking the end of the OS-independent hard drive boot phase.
However, the MBR may be overwritten with program code that does not follow this script, e.g. using code that bypasses the BIOS disk handling routines so as to work around compatibility issues, or malware code with an agenda of its own. In fact, there might be utter garbage in this sector, but as long as it ends in 55AA hex, it will be jumped into by BIOS.
When such circumstances arise, a black screen hang is common, and the last displayed text message (typically "Updating ESCD...") is assumed to be where the problem lies. Some modern BIOSs are more helpful; the BIOS displays a message describing which device is being booted before jumping into it!
Once you have got this far, you are (for the first time) within an operating system (OS). Up until FAT32, the DOS-Win9x series of OSs used to fit the partition boot record within the fist sector of the volume, and the FAT would follow immediately thereafter. FAT32 is different; it uses the first three sectors for the boot record, but behaves the same in other respects.
The boot code of a Microsoft DOS/Win9x bootable partition is expected to seek a file called IO.SYS and jump into it. Win9x boot loaders have sufficient file system smarts to load an IO.SYS no matter where it lies within the disk volume, but some earlier DOS versions required the file to be contiguous and starting from directly after the end of the root directory.
Once again; that's what is expected to happen - but it's entirely up to whatever code is written there, as to what actually does happen. As long as the first sector of the active partition ends with 55AA (hex), the MBR will jump into it, and from that moment on, the code has total control. Both the partition boot record and the MBR have long been traditional entry targets for malware.
IO.sys is the first file to load in the DOS or Win9x boot process, and is also the first code to write to the screen since the BIOS passed control to the MBR. So if anything goes wrong up until this point, there'd be no visible clues as to where the problem arose. In fact, really old versions of MS-DOS didn't display anything here either; there'd be nothing visible until Command.com unless some device driver loaded by Config.sys output something to the screen.
Win9x IO.sys displays a text message such as "Loading Microsoft Windows..." before getting down to business. During this process, it will look for a Logo.sys file and display that as a low-resolution 256 color bitmap if found, and "animate" the bottom of it. If no Logo.sys is found, an internal logo is extracted from within itself and used instead. Note that this logo display is suppressed if the registry check indicates a "Specify a new..." DOS mode .pif session is in progress, or if suppressed by a setting as described in the next section.
In MS-DOS prior to Windows 95, IO.sys would load more code contained in MSDOS.sys, and would then load and interpret Config.sys, but that changed slightly in MS-DOS 6, with the advent of bundled disk compression. It changed completely in Windows 95, as all the code that used to be in IO.sys and MSDOS.sys is now in the single IO.sys file. It changed again in Windows ME; now the hard drive form of IO.sys appears to contain all the code functionality that used to reside in IO.sys, HiMem.sys, IFSHlp.sys and presumably SetVer.exe
In Windows 9x, both of these are ASCII (text) settings files with the same .ini file syntax. Typically there is no WinBoot.ini present and MSDOS.sys is used, but if a Winboot.ini exists, it is used instead. Note that at this stage, the embryonic operating system (OS) still has no knowledge of any directories other than the root of the hard disk volume that is being booted.
These settings files cannot load program code, but the [Paths] section informs IO.sys where Windows resides. The [Options] section controls various matters, such as whether a boot menu should be displayed in response to an F8 keypress, which boot menu entry should be taken as the default, whether disk compression drivers should be loaded, whether a logo screen should be displayed, and whether the system should boot into Windows or DOS mode.
These settings are documented in the Resource Kit (pity the poor WinME user there) and at numerous other sites on the web, so I'll spend no more bytes on the matter here! One thing of interest; IO.sys checks the registry before displaying the boot menu (if prompted to do so, or set to do so without prompting).
If neither WinBoot.ini nor MSDOS.sys exist, the system cannot load Windows as no path to it is set.
NB: Because Config.sys allows code to be loaded and executed, it is a risk point for malware.
After processing WinBoot.ini (usually not present) or MSDOS.sys (usually present) and acting accordingly, Config.sys is loaded and interpreted by IO.sys. The file extension suggests this is a real-mode device driver, but in fact it is an ASCII (text) file that controls the device management level of the real-mode boot process. The file uses standard .ini syntax, but predates .ini files by many years; it's a relic of the very early days on MS-DOS.
Note that Windows Millennium ignores Config.sys completely, and destroys it (overwrites with a blank copy) when shutting down Windows. This has implications if you try to set up some sort of hard drive based DOS mode in WinME, but it does wall out risks from malware being loaded from there.
The search for a full description of possible Config.sys contents is "left as an exercise for the reader"; it's documented by the MS-DOS 6.x Help command, and within the Resource Kit reference found on all Win9x CDs other than Windows ME (alas, they have some surfing to do).
Two critical settings are particular parameters for the DOS statement.
DOS=Single will cause Win95-to-Win98SE systems to boot into DOS mode rather than Windows, and this will typically occur only when a "Specify a new..." DOS mode .pif is in session.
DOS=NoAuto reverses the implicit DOS=Auto default, and causes the boot process to skip default setting values and the loading of HiMem.sys, IFSHlp.sys and Setver.exe from the Windows subtree.
If there is a [Menu] in Config.sys, the choice made there is passed on via the %Config% environment variable.
You can use SysEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit Config.sys; SysEdit will allow direct editing and creates a Config.syd backup of the original file.
NB: Because AutoExec.bat allows code to be executed, it is a risk point for malware.
At this point in the boot process, a functional DOS mode is present.
If a C:\AutoExec.bat exists, even if it is empty, then a command interpreter is loaded to interpret it. Unless a setting within Config.sys overrides the default, that interpreter will be Command.com; that's the program that interprets batch files and provides the command prompt in DOS and Windows.
If no C:\AutoExec.bat exists, and the system is on track to load Windows, then Command.com is not loaded underneath Windows - a good reason to avoid the existence of the file.
Note that Windows Millennium ignores AutoExec.bat other than to lift Set, Path and Prompt statements from it and integrate these into the registry. It also destroys the file (overwrites with a copy full of Set statements) when shutting down Windows. This has implications if you try to set up some sort of hard drive based DOS mode in WinME, especially when it comes to setting a version-appropriate Path, but it does wall out risks from malware being loaded from there.
AutoExec.bat is a batch file, and you can do anything you can do with a batch file in it - bearing in mind that all DOS mode limitations apply. There is only one peculiarity; the Windows base directory and its Command subdirectory are used as a stub if the first Path statement should fail to use %Path% to include these. If subsequent Path statements within Autoexec.bat fail to include these directories in the Path, they are left out.
You can use SysEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit AutoExec.bat; SysEdit will allow direct editing and creates a Autoexec.syd backup of the original file.
NB: Because WinStart.bat allows code to be executed, it is a risk point for malware.
WinStart.bat is interesting, as it lives in a twilight world between DOS and Windows; Long File Names can be used as parameters and are displayed by Dir, but there is no multitasking as yet (Set statements apply globally) and Win32 command line utilities such as WinSet.exe will exit via their "This program requires Windows" real-mode stub. It is typically used by Win3.yuk-era installers in the same way that Win9x installers would use Wininit.ini or the registry RunOnce and variations.
Windows Millennium appears to use WinStart.bat internally, yet ignore most if not all additions there. This may have a protective effect against malware that uses this file to escalate.
After WinStart.bat is interpreted, Windows is loaded and multitasking begins.
I am unclear as to whether Win.com is required to launch Windows in Win9x (I had heard that it wasn't) but it does appear necessary to text for file system errors markers and interpret the WinStart.bat, if that exists in the Windows base directory.
When ScanDisk.exe is run with the /Custom switch, it uses ScanDisk.ini to determine its response to errors, and whether it should log the results of the scan. When Win.com (or whatever) starts the Windows process, it checks bits within the FAT of every hard disk volume for two markers.
One is set if the system failed to read or write to the hard drive due to physical errors, and if set, ScanDisk will perform a surface scan of all volumes on that physical disk.
The other is set when Windows begins a file write and is reset when this is completed - so if set at boot time, implies a file write was interrupted during the last session (by crash or bad exit) and therefore there is at least one corrupted file on that volume, so ScanDisk will perform file system checks for logical errors on the affected volume.
When ScanDisk.exe is autorun in this way, the /Custom switch is used, and so ScanDisk.ini controls the process. The default settings for various versions of Windows 9x are as follows:
Windows ME runs the Windows ScanDiskW.exe rather later in the process should the same factors apply, and although ScanDisk.ini exists, it is not used. In fact it's hard to imagine why a ScanDisk.ini should exist, given that there's no real-mode ScanDisk.exe in WinME! Whereas ScanDisk.ini allows detailed control over actions to be taken for each error, WinME only allows "Prompt before fixing errors and Auto-ScanDisk" and logging control, and defaults to data slaughter mode ("Fix" everything and Delete all traces of recovered data). These settings are set via the Advanced button within WinME's Windows ScanDisk itself.
The nature of many logical file errors, and almost all physical errors, is that information is lost and thus perfect repair is impossible. As long as the fault is not repaired, ScanDisk can detect it; once ScanDisk "fixes" it, the file will no longer be flagged as an error by ScanDisk, yet is is probably broken. So without a log of what was done, you no longer have a way of finding out which of several thousand files would have to be replaced. If ScanDisk is allowed to Delete data clusters with physical errors, or lost cluster chains that were recovered, another opportunity to repair damage is lost.
For these reasons, the default ScanDisk.ini settings are irresponsible and have become more so in later versions.
NB: Because these Runxxx keys allow code to be executed, they are a risk point for malware.
At this point, Windows is running; multitasking is present, Set statements made by DOS applications will not be global, and Windows programs can be launched. For this reason, my lack of clarity as to which part of the startup axis runs next is perhaps meaningless, as processes that are started earlier may only start getting into their stride after other processes have already completed.
The only way to serialize the execution of Windows programs is to launch these from a batch file, using Start /W to cause each to delay further interpretation of the batch file until the process ends. But there is a catch here; many Windows programs chain into other programs, so Start /W may not wait until the "whole process" ends.
The Runxxx keys are variations on Run, RunEx, RunOnce, RunServices and RunNetworkServices (e.g. there's often a RunServicesOnce). It's unclear whether there's any sequence significance to these, although they differ in other respects. The ones covered here reside in (deep breath): HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion
RunOnce entries (and variations) will be cleared from the registry after they have been run, and are thus often used by installers and malware.
RunServices (and variations) may cause their processes to be hidden from the Ctrl-Alt-Del tasklist; these keys are often used by antivirus utilities and malware.
RunEx (and variations) are documented by Microsoft to be a new and preferred form of Run.
HKEY_LOCAL_MACHINE is held in the System.dat registry file, but you cannot edit this directly as it is a "structured" file with undocumented structure. But you can use RegEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit these Runxxx keys. RegEdit allows more direct editing, but changes are made "live" and there is no sanity-checking to stop you chopping up something else by mistake.
Windows 95 keeps one backup set of the System.dat and User.dat registry files with the extension .da0, but is rather hasty about assuming success before splatting these backups with the current set. The original fresh-install System.dat is kept as C:\System.1st
Windows 98 and Windows ME also retain the original as C:\System.1st, but keep multiple backups in other ways - but there's no substitute for your own known-circumstance registry backups. Note that Windows ME has split off HKEY_CLASSES_ROOT into its own Classes.dat file, with it's own C:\Classes.1st fresh installation backup.
NB: Because Wininit.ini allows code execution and installation, it is a risk point for malware.
Somewhere during the pre-login phase of Windows, Wininit.exe will interpret a Wininit.ini file, if this is present in the Windows base directory. This file is typically used by installers, and it may be that Wininit.ini is cleared or deleted after use.
NB: Because System.ini allows code execution and installation, it is a risk point for malware.
System.ini dates from Windows 3.yuk, and so may be used by Win16 programs (all of which are registry-unaware). The function of System.ini within Win3.yuk is analogous to the function of Config.sys in DOS; this is where device drivers and core system settings were made. The registry is now the approved place for such settings, but the Win3.yuk settings files are retained for legacy support.
Within the [Boot] section is a Shell= directive that determines what program will be the user interface shell. This used to mean that program that causes Windows to close when it is closed, but at least in the case of Explorer.exe (the default shell), closing the zeroth instance of this simply causes it to be re-launched - though the startup axis is not. That is why when Explorer crashes in Windows, you lose everything that was in the System Tray; SysTray.exe is an entry within the startup axis.
The Shell= line is commonly exploited by malware, with "Expiorer.exe" (spelled with a capital "i") being one of the sneakiest examples. Unless you have replaced Explorer.exe with a shell of your own, the line should read Shell=Explorer.exe with nothing thereafter until the next line.
Further significant settings and device driver loads may follow in the [386Enh] section (Windows 9x always runs in "386 Enhanced Mode", as "Standard Mode" was abandoned in Windows for Workgroups 3.11, and "Real Mode" Windows was abandoned in Windows 3.1). Internal code uses "illegal" file names starting with *, e.g. device=*ebios.vxd, and there are other clues to spot likely add-ins:
Windows 9x may cross-update settings between the Win16-era .ini files and the registry, so if changes to one or the other do not appear to "stick", look at the others.
You can use SysEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit System.ini; SysEdit allows direct editing and creates a System.syd backup of the original file. In addition, a copy of the original fresh-install System.ini is kept as System.cb, and other installers may leave backup copies with different extensions (but not .dat or .da0!).
NB: Because Win.ini allows code execution, it is a risk point for malware.
Win.ini dates from Windows 3.yuk, and so may be used by Win16 programs (all of which are registry-unaware). The function of Win.ini within Win3.yuk is analogous to the function of AutoExec.bat in DOS; this is where user settings were made and programs launched. The registry is now the approved place for such settings, especially when used in conjunction with user profiles, but the Win3.yuk settings files are retained for legacy support.
The Run= and Load= lines will cause other files to be loaded on startup, and should be checked for malware. This is a particularly common method of extension across LANs; often used together with a hunter-killer payload, e.g. Zipped_Files and LoveLetter.
Windows 9x may cross-update settings between the Win16-era .ini files and the registry, so if changes to one or the other do not appear to "stick", look at the others. This may be particularly significant where file associations are concerned.
You can use SysEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit Win.ini; SysEdit allows direct editing and creates a Win.syd backup of the original file. Other installers may keep backups of Win.ini with other extensions (but not .com or .bat!).
NB: Because AllUsers allows files to be launched or left on desktop, it is a risk point for malware.
Any contents of this folder will be handled as per the StartUp group, except that these will be applied regardless of what logon identity is used. So check this when eyeballing for malware, and check the AllUsers subtree if puzzled by desktop and Start Menu shortcuts that don't appear in the expected folders.
This may pass unnoticed where there's no LAN present, or if suppressed by TweakUI, but it marks the change from that part of the Windows startup axis that applies to all users, and that which may vary according to User Profiles and logon identity.
Each user profile is held as a branch of HKEY_USERS, and the one that is logged into is then aliased as HKEY_CURRENT_USER. This is important if you are trying to exclude items from the startup axis, or if you wish to migrate registry settings across user profiles (e.g. as part of the management after an application that was installed under one user profile is not present in other user profiles).
You should also look at the ShellFolder entries in each profile to see where the Desktop, Send To, Start Menu and StartUp group might be located for each profile.
A cancelled logon will preclude access to LAN and remembered network/Internet passwords, but will not prevent other systems from accessing shared folders or printers on the system. If logon is cancelled, the .Default user profile is used - so by setting this very restrictively and perhaps with horrible desktop colors, you may be able to discourage users who cancel logon (and then complain the "Internet doesn't work") and mildly limit the activities of those who shouldn't be there.
NB: Because these Runxxx keys allow code to be executed, they are a risk point for malware.
These are similar to those in HKEY_LOCAL_MACHINE, except they apply only to the current user. See HKEY_LOCAL_MACHINE and Windows Logon for notes about the Runxxx keys and how to manage multiple user profiles, each of which can be used depending on "who" logs in. Some malware and applications (e.g. AOL Instant Messenger, as rammed in by early Netscape 4.xx) use these, making them difficult to root out if you are used to checking only HKLM.
HKEY_USERS (and thus HKEY_CURRENT_USER) is held in the User.dat registry file, but you cannot edit this directly as it is a "structured" file with undocumented structure. But you can use RegEdit.exe in all versions of Windows 9x, or MSConfig.exe in Windows 98 and later, to edit these Runxxx keys. RegEdit allows more direct editing, but changes are made "live" and there is no sanity-checking to stop you chopping up something else by mistake.
Windows 95 keeps one backup set of the System.dat and User.dat registry files with the extension .da0, but is rather hasty about assuming success before splatting these backups with the current set.
Windows 98 and Windows ME also retain the original as C:\System.1st, but keep multiple backups in other ways - but there's no substitute for your own known-circumstance registry backups. Note that Windows ME has split off HKEY_CLASSES_ROOT into its own Classes.dat file.
NB: Because StartUp allows files to be launched, it is a risk point for malware.
Any contents of this folder will be launched as per file associations when Windows starts, e.g. shortcuts to folders will cause folder windows to appear, etc. The best way to edit this is to Rt-click the Start button and choose Explore; if you just presume the location to be directly under the Windows base directory, you may be editing the wrong folder if User Profiles has redirected the StartUp object location. You can also use MSConfig.exe in Windows 98 and later, to enable or disable these entries.
(C) Chris Quirke, all rights reserved - January 2001