The NTLDR Hacking Guide
Copyright © 1996, 2022 by Jay Locke
This guide describes how to boot Windows NT, Windows 95, Linux and old versions of DOS using NTLDR.
Additional documents
Boot Sector
Master Boot Record
This is a boot sector taken from my active, boot-able drive. I have commented it 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.
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.
Table of Contents
- 1. General Information
- 1.1 Overview of the boot sequence
- 1.2 Problems with multiple operating systems
- 1.3 The NTLDR
- 1.4 Format of BOOT.INI
- 2. The Various Boot Sequences
- 2.1 Systems with only Windows NT
- 2.2 Systems with only Windows 95/MS-DOS
- 2.3 Systems with only MS-DOS
- 2.4 Systems with only Linux
- 3. Booting Windows 95 With NT
- 3.1 Installing Windows 95 after Windows NT
- 3.2 Installing Windows NT after Windows 95
- 3.3 After the installation of NT and Windows 95
- 3.4 Booting DOS from Windows 95 by pressing F4
- 4. Booting DOS Directly From NTLDR
- 4.1 What is BOOTSECT.DOS?
- 4.2 Obtaining a boot sector for an earlier version of DOS
- 4.3 Configuring BOOT.INI correctly
- 4.4 Windows 95 and older MS-DOS use the same CONFIG and AUTOEXEC
- 5. Booting Linux Directly From NTLDR
1. General Information
1.1 Overview of the boot sequence
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.
1.2 Problems with multiple operating systems
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.
1.3 The NTLDR
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.
1.4 Format of BOOT.INI
Here is a sample of my BOOT.INI file:
[boot loader] timeout=10 default=multi(0)disk(0)rdisk(0)partition(4)\WINNT35 [operating systems] multi(0)disk(0)rdisk(0)partition(4)\WINNT35="Windows NT..." 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:
multi(0)disk(0)rdisk(x)partition(y)\<dirname>
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.
2. The various boot sequences
2.1 Systems with only Windows NT
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.
2.2 Systems with only Windows 95/MS-DOS
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. 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.
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. Dumb but true.
2.3 Systems with only MS-DOS
As mentioned before, MS-DOS uses the files MSDOS.SYS, IO.SYS, CONFIG.SYS, AUTOEXEC.BAT and COMMAND.COM to configure itself.
2.4 Systems with only Linux
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. Note that for hard disks, the boot sector program is ignored by Linux.
3. Booting Windows 95 with NT
3.1 Installing Windows 95 after Windows NT
When I installed Windows 95, I had Windows NT from a previous install on my system. Everything discussed here will be under this assumption.
3.2 Installing Windows NT after Windows 95
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:
I have done this recently on my home system. My system currently has 3 drives and 4 operating systems (Windows 95, OS/2, NT 3.51, and FreeBSD). Installing Windows NT after Windows 95 resulted in an NTLDR boot menu that included "Microsoft Windows" as the last line in the NTLDR menu. Otherwise, (remarkably) it did not trash the Windows 95 boot at all. My current BOOT.INI is included below:
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(2)partition(1)\WINNT35 [operating systems] 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".
3.3 After the installation of NT and Windows 95
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.
3.4 Booting DOS from Windows 95 by pressing F4
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:
[Options] BootGUI=1 BootMulti=1 DblSpace=0 DrvSpace=0
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.
4. Booting DOS Directly From NTLDR
4.1 What is BOOTSECT.DOS?
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.
4.2 Obtaining a boot sector for an earlier version of DOS
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 direct way to do this is to make your system boot into DOS, by booting into DOS initially with a boot floppy, and then executing the following command:
sys c:
If you reboot after executing this command, your machine will drop you into a DOS command prompt immediately. If you boot into Linux, executing the following command will extract the bootsector into a file called bootsect.dos:
dd if=/dev/hda1 of=bootsect.dos bs=512 count=1
This works because /dev/hda1 refers to the first logical (IDE in this case) drive in the system, as opposed to the first physical disk (which may contain multiple logical drives).
Please note that before executing these commands, you should make backups of your master boot record and bootsector so that your original configuration can be restored (the 'dd' command under Linux does this nicely). The process is ugly because it was never meant to work this way, and so a certain amount of coaxing is required on the part of the techie.
4.3 Configuring BOOT.INI correctly
After the above steps, you will have two 512 byte programs at your disposal. 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 (and the bootsect files are in the root directory):
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.
4.4 Windows 95 and old MS-DOS use the same CONFIG and AUTOEXEC!
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. Use your favorite hex editor (this is a hacking guide you know).
5. Booting Linux directly from NTLDR
5.1 General procedure
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). The process is similar to section 4.2. Make LILO boot your Linux system, and then extract where LILO lives to a file using 'dd'.
Again, the Linux dd program can read the master boot record and write it to a file.
5.2 Generating the right master boot record program to boot Linux
Boot the Linux system, and rewrite the boot record with 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.
5.3 Writing LILO to a file using 'dd'
Once LILO has been written to the master boot record, 'dd' can extract it into a file like so:
dd if=/dev/hda of=mbr.lin count=1 bs=512
Since we are dealing with physical drives, /dev/hda corresponds to the first physical drive in the system (in this case, an IDE drive).
Once this is done, the master boot record needs to be restored to it's original state. This can be done without dd (under Windows) by using an undocumented switch from the command line execution of FDISK:
fdisk /mbr
You could also do this under Linux by writing a backup version of the master boot record using 'dd' like this (assuming your backup is in a file 'mbr-win.bin'):
dd if=mbr-win.bin of=/dev/hda count=1 bs=512
5.4 Configuring BOOT.INI correctly
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
Thanks to my associate Dennis Lynster for the required brain food in order to create this document and also to the following human beings:
- Brian Hall for sending me the Microsoft Knowledge Base article on the geometry of the BOOT.INI file.
- Gary Hanson for writing to me about my error in the description of BOOT.INI, and also for the details on installing Windows NT after Windows 95.
- Yinrong Huang for revealing the meaning of two pieces of assembly code in BOOTSECT.TXT that had remained a mystery until then.
Copyright © 1996, 2022 by Jay Locke