The NTLDR Hacking Guide
by Jason C. Locke
Last Modified: September 15, 1996
In addition to this document, additional documents and programs are available from the author free of charge.
These are the diagrams that visually illustrate the booting procedures for Windows NT, Windows 95 and MS-DOS. The file names and formats are as follows:
This is a program that reads and writes Boot Sectors and Master Boot Records directly from the command line. Instructions on how to use this program are descibed later in this document in a sample batch file.
This is a program that modifies IO.SYS and COMMAND.COM to use CONFIG.622 and AUTOEXEC.622 as MS-DOS configuration files instead of the conventional ones.
This is a batch program that will attempt to make a file containing an MS-DOS boot sector program. It makes calls to the BOOT.EXE program as described above, and is helpful in seeing the application of BOOT.EXE. GETBS.BAT works on my system fine, but your mileage may vary.
This is a boot sector taken from my active, boot-able drive. I have commented as much as possible, but a few areas remain a little thin. Note that the boot sector in question was created by MS-DOS 6.2. This file is not designed to be re-assembled.
This is a master boot record taken from the same drive as described above. It is simpler to follow than the boot sector, and only a few comments were entered. This file was created by MS-DOS 6.2, and is not designed to be re-assembled.
Most of the information in this document can be obtained directly from Microsoft for a princely sum of money. Rather that pay for expensive books that only describe an overview of the boot process, I decided to analyze the boot sectors for the various operating systems and explain the execution of them with as much detail as possible.
Some of the information found in this document cannot be found anywhere else, particularly the discussion of the boot process in section 1.1. My time and effort has not gone to waste because of this document. It is my hope that this document will answer the questions most people do not think to ask, but are still interested in having them answered nonetheless.
When an Intel based computer system is turned on, the BIOS goes through a simple procedure that triggers the booting of an operating system. The BIOS reads the first physical sector of the disk into memory locations 0000:7C00 through 0000:7DFF and performs a JMP to it.
On hard disks, the first physical sector is the Master Boot Record. For floppy drives, the first physical sector is the Boot Sector. The master boot record is needed for hard disks because hard disks can be partitioned into multiple logical drives. The BIOS does not care whether it is loading a master boot record or a boot sector. When booting from hard disks, the master boot record moves itself to 0000:0600, and then overwrites it's original location (0000:7C00) with the boot sector. When booting from a floppy drive, which has no partitioning information and therefore no master boot record, only the boot sector is effectively loaded.
The master boot record program is simpler to follow in comparison to the boot sector program (examples of both programs for DOS based systems may be obtained in commented assembler source from the author's web page). A DOS boot sector program actually overwrites sections of itself in order to squeeze BIOS data into the 512 byte block of usable memory. Why it does this instead of simply using another region of memory to store the BIOS data is beyond me.
The boot sector is a somewhat ugly assembler program to look at. When the boot sector is executed, none of the DOS interrupt handlers are in place yet. Everything must be done through the BIOS. The actual code in the boot sector varies depending on the operating system, yet it always attempts to boot the operating system. Note that the format of the disk is irrelevant, as the boot sector program uses only physical addresses and low level BIOS functions to access the drives.
Since the BIOS blindly loads the first physical sector on the disk and executes it, any setup dealing with multiple operating systems must be done at the boot sector level. While this seems easy enough, a physical sector is only 512 bytes in size. This doesn't leave much room for fancy code and pretty menus. This is not to say it cannot be done, however.
When a system is configured with Windows NT, the NT boot sector loads and executes NTLDR. NTLDR is the program that displays the OS loader startup menu.
From NTLDR any operating system can be loaded and successfully installed as long as a copy of the operating systems boot sector program resides in a file pointed to by BOOT.INI (more about BOOT.INI later).
Linux modifies the master boot record in order to boot itself. This complicates things slightly, since the master boot record is executed before the boot sector (remember, the master boot record loads before the boot sector). Linux boots before NTLDR can be called upon. The solution to this problem will be discussed later in this document.
Here is a sample of my BOOT.INI file:
C:\BOOTSECT.W40 = "Windows 95" /WIN95
C:\BOOTSECT.DOS = "MS-DOS 6.20" /WIN95DOS
C:\MBR.LIN = "Linux 1.1.59"
To boot the Windows NT operating system, the BOOT.INI must contain the physical location of the WINNT35 directory. The WINNT35 directory can be on any drive or partition as long as BOOT.INI dictates exactly where it is. This allows the administrator to change the way NT loads without rewriting the boot sector on every machine on the network. Copying over a new BOOT.INI file will effectively do the same thing.
My system's disk drives are all IDE. Therefore, the location of my WINNT35 directory will always be of the form:
For Intel based systems, the parameters for multi() and disk() are always zero. The parameter for rdisk() is the number corresponding to the physical drive of the WINNT35 directory. The parameter for partition() specifies the partition number. The range of values for partition() begin at 1, not zero as common sense would dictate. Finally, <dirname> is the name of the NT installation directory on the specified partition.
Notice that any operating system other than NT can be loaded by creating a 512 byte file containing a copy of the boot program that will load the desired operating system. Windows NT, MS-DOS and Linux are all loaded via boot programs. Apparantly you cannot use the same method of locating these boot files as done when locating the NT installation directory.
Notice also the switches at the end of C:\BOOTSECT.DOS and C:\BOOTSECT.W40. These switches are needed because of the renaming procedure Windows 95 uses to boot itself and old versions of DOS. This will be discussed later in the document.
For complete information on the so called "ARC Paths" syntax, view the Microsoft Knowledge Base article at Microsoft's Web Site.
The NT boot sector loads NTLDR, which displays the OS loader menu. Choosing Windows NT at this point will run NTDETECT.COM to poke around the users hardware setup. The rest is unimportant for our purposes.
Page 1 of the Visio documents show the boot sequence of Windows NT.
Because Windows 95 claims to be compatible with old software, old software running under Windows 95 must be tricked into thinking it is running under the "right" version. A good example of this is MSCDEX.EXE running under MS-DOS 6.x which must be fooled by SETVER.EXE into thinking it is running under MS-DOS 5.x.
In addition to this, some applications check the root directory for certain files in order to change the configuration of DOS and Windows. Windows 95 uses the same names for it's configuration files as DOS. These files are: MSDOS.SYS, IO.SYS, CONFIG.SYS, AUTOEXEC.BAT and COMMAND.COM.
This causes a slight problem. What if DOS 6.2 was the most recently loaded? When Windows 95 boots up, it assumes it's configuration files are MSDOS.SYS, IO.SYS, etc. In order to fix this problem, Microsoft decided to rename all the DOS configuration files to MSDOS.DOS, IO.DOS, CONFIG.DOS, AUTOEXEC.DOS and COMMAND.DOS, then rename MSDOS.W40, WINBOOT.SYS, CONFIG.W40, COMMAND.W40 and AUTOEXEC.W40 to MSDOS.SYS, IO.SYS, CONFIG.SYS, AUTOEXEC.BAT and COMMAND.COM. The reverse is done when Windows 95 was most recently loaded, and the user wishes to load an old version of DOS.
Pages 2, 3, and 4 of the Visio documents show the boot sequence of Windows 95 as well as the renaming pattern.
Windows 95 may know if it has to rename anything by checking for the presence of WINBOOT.SYS. If WINBOOT.SYS exists, then an old version of DOS was most recently loaded, and the renaming operations must be performed. Whether or not Windows 95 actually does this is unknown to me (anyone?).
Note that you cannot have separate CONFIG and AUTOEXEC files for DOS and Windows 95 unless you use the Windows 95 menu to load the previous version of DOS. Even the /WIN95 and /WIN95DOS switches in BOOT.INI do not rename the CONFIG and AUTOEXEC files. This is stupid but true.
As mentioned before, MS-DOS uses the files MSDOS.SYS, IO.SYS, CONFIG.SYS, AUTOEXEC.BAT and COMMAND.COM to configure itself.
Page 5 of the Visio documents show the boot sequence MS-DOS.
The details of the Linux boot process is a mystery to me beyond the basic sequence. LILO will write to the master boot record a program to boot Linux, thereby bypassing the boot sector. If you make a bootable floppy, Linux will write pretty much the same code to the boot sector on the floppy. I suppose the only difference between the two is the parameters for the disk layout for the BIOS (anyone?). Note that for hard disks, the boot sector program is ignored by Linux.
When I installed Windows 95, I had Windows NT from a previous install on my system. Everything discussed here will be under this assumption.
I have never experimented with this. On page 225 of the Microsoft Windows 95 Resource Kit, running WINNT /W will install NT. What happens after this is a mystery to me. However, the following was Emailed to me by Gary Hanson:
multi(0)disk(0)rdisk(2)partition(1)\WINNT35="Windows NT Workstation Version 3.51"
multi(0)disk(0)rdisk(2)partition(1)\WINNT35="Windows NT Workstation Version 3.51 [VGA mode]" /basevideo /sos
C:\ = "Microsoft Windows"
Also, you mention the "WINNT /W" in the Windows 95 Resource Kit. I looked this up and it does not appear to be particularly significant. I guess you would use "WINNT /W" if you wanted to install Windows NT from Windows 95 or Windows 3.1x. It does not do anything special as far as I know except tell the Windows NT installer where you are installing from. I installed Windows NT from DOS, with "WINNT /B". The "/B" flag is a barely documented (but very useful) flag saying "skip all the floppy writing stuff and just do the install".
You should have Windows NT installed as well as Windows 95, both accessible from NTLDR. If not, close this document and do it.If you look at the BOOT.INI file at this point, you should see an entry similar to this:
C:\BOOTSECT.DOS = "DOS"
Even though it is named "DOS", this boot sector contains code that will boot Windows 95, giving the user an option to load the old version of DOS as well. If you do a directory of your C: drive, you'll see that BOOTSECT.DOS is 512 bytes, the size of a physical sector. This file will later be renamed BOOTSECT.W40, but for now leave it as is.
Windows 95 uses the file MSDOS.SYS to configure itself early on. MSDOS.SYS for Windows 95 is a simple DOS Text File. A sample MSDOS.SYS file is as follows:
; The lines required for compatibility with other programs
; have been deleted here for brevity.
The line BOOTMULTI=1 means that Windows 95 will listen to the F4 key to determine if the user wishes to load the old version of DOS instead of Windows 95.
When DOS is the only active operating system, it is loaded by the boot sector program. When Windows 95 is active along with an earlier DOS version, Windows 95 apparently boots DOS directly from the same boot sector program that boots Windows 95. Note that if the line BOOTMULTI=1 does not appear in the MSDOS.SYS for Windows 95 the F4 key is effectively ignored.
It was mentioned earlier that BOOTSECT.DOS is not a DOS boot sector program, rather it is a Windows 95 and DOS combination of boot sector programs. This means that in order to boot DOS from NT, you have to tell NTLDR you want to load Windows 95, then tell Windows 95 that you really wish to load the previous version of DOS. The purpose of this document is to get around this.
Since we want to boot DOS directly from NTLDR, we need to supply NTLDR the name of the file that will boot DOS directly. This is simply the boot sector that loads MS-DOS directly. Windows 95 will have nothing to do with this process.
The most generic way to do this is going to require a little juggling. The GETBS.BAT batch program will create an MS-DOS boot sector program on the C: drive, extract it into a file called BOOTSECT.DOS, and replace the boot sector with whatever was there before, leaving your system in the state is was in before running the batch program.
To do this correctly, boot up the older version of DOS using the first setup disk before running the program.
You may have noticed a command used in the above program that is nowhere in the MS-DOS documentation. That is because it is not in MS-DOS. The program BOOT.EXE can be obtained from the author's web page. The address is listed in the beginning of this document.
BOOT.EXE is a little program I developed to do the dirty work I do with the MS-DOS DEBUG program from the command line more easily. Typing BOOT /? will display a help screen, although I think that GETBS.BAT is a better example of BOOT.EXE's usage.
After the sample batch program above, there will be two 512 byte programs in the root directory on your C: drive. BOOTSECT.DOS is the boot sector for the older version of DOS, and BOOTSECT.W40 in the combination MS-DOS/Windows 95 boot sector that loads Windows 95 if you leave it alone. Make sure that these two lines appear in BOOT.INI:
C:\BOOTSECT.W40 = "Windows 95" /WIN95
C:\BOOTSECT.DOS = "MS-DOS 6.20" /WIN95DOS
At this point, boot up you computer and take note at an annoying side effect.
After all this work we find out that NTLDR will not rename the CONFIG and AUTOEXEC files in the same way that the Windows 95 menu automatically does. This makes sense, since Windows NT was released years before Windows 95. Remember the phrase, "640K is plenty for any application."
The only apparant solution is to modify the older verison of MS-DOS's IO.SYS and COMMAND.COM files to use something other than CONFIG.SYS and AUTOEXEC.BAT respectively.
This part is incomplete, as a program to do this easily is under work. Look for the program ALTER.EXE to eventually do the modifying. Check the author's web page periodically for any news on ALTER's progress (simple program, little time to do it in).
Booting Linux from NTLDR is very simple. All the Linux configuration files are located in the Linux partition. What is needed is a file that contains the Linux master boot record program which is commonly called LILO (Linux Loader).
Acquiring the master boot record cannot be done from DEBUG. I originally used Norton's Diskedit program to read the physical sector into the clipboard, then save it to a file. The program BOOT.EXE will do this in one line from the command prompt.
Boot the Linux system. Since the lilo configuration utility is easy to use, I will not discuss how it is done. If you managed to get Linux running in the first place, you do not need my help in setting up LILO.
A couple of notes: LILO should be configured to boot only Linux with no delay, since the choice will be left up to NTLDR as to what operating system will be loaded. Also, before running LILO you should make a boot disk that will bring you to a MS-DOS prompt.
Once LILO has been written to the master boot record, BOOT.EXE can extract it into a file like so:
boot /r /drive:0 mbr c:\mbr.lin
Since we are dealing with physical drives, /DRIVE:0 corresponds to the first physical drive in the system. MBR instucts BOOT.EXE to read from the first physical sector which contains the master boot record commonly referred to as LILO.
Once this is done, the master boot record needs to be restored to it's original state. This can be done without BOOT.EXE by using an undocumented switch from the command line execution of FDISK:
Adding the following line to BOOT.INI will create a menu option in NTLDR to boot Linux:
C:\MBR.LIN = "Linux 1.1.59"
Thanks to my associate Dennis C. Lynster for the required brain food in order to create this document and also to the following human beings: