Why can you create a PIF file that points to something that isn’t an MS-DOS program?


James MAstros asked why it’s possible to create a PIF file that refers to a program that isn’t an MS-DOS program. (That’s only part of the question; I addressed other parts last year.)

Well, for one thing, there was indeed code to prevent you from setting PIF properties for something that isn’t an MS-DOS program, so the precaution was already there. But it didn’t stop anybody who was really determined to try. All you had to do was create an MS-DOS program, then create a PIF file for it, and then overwrite the MS-DOS program file with something else. Since time travel has not been invented, the PIF creator code can’t retroactively go back in and say, “Well, if I knew you were going to pull this trick, I wouldn’t have let you create it in the first place!” You can’t even enforce it at the time the PIF file is launched, because somebody could replace the file during the split second between checking the file type and actually using it.

Of course, the real question is “Why, if you create a PIF file that describes something that isn’t an MS-DOS program, does it still work?” It still works because the PIF file did exactly what it was supposed to do. It created an MS-DOS virtual machine with the specified parameters and then ran the program in it.

Now, back in the days when PIF files were invented, if you tried to run something that wasn’t an MS-DOS program inside an MS-DOS virtual machine, all that happened was that the MS-DOS stub ran, the same thing that happened if you tried to run the program from MS-DOS. The program was treated not as a Windows program but as an MS-DOS program.

Windows 95 changed that. If you tried to run a Windows application from the MS-DOS command prompt, it would run the Windows application instead of telling you, “This program cannot be run in DOS mode.” This change was made for two reasons.

First, the existing behavior seemed pretty stupid. You’re running Windows, and if you open a command prompt and try to run a Windows program, you’re told, “You need Windows to run this program.” It’s like one of those bizarro-land government red tape nightmares, where you go to the courthouse to file some papers in person, and the clerk at the desk says, “I’m sorry, you have to file this document in person at the courthouse.”

Second, it was necessary to allow 32-bit console programs to run when launched from a MS-DOS command window. Since Windows 95 used the MS-DOS prompt as its command line interface (as opposed to Windows NT which used a 32-bit command prompt), it was kind of important that you be able to run 32-bit console programs from a virtual machine. Without it, the whole idea of a console program became kind of weak. “Yeah, we have console programs, but you can’t launch them from a console.”

What happens, then, if you create PIF file that points to a 32-bit program? Well, the operating system goes to all the effort to create a virtual machine to the specifications you indicated in the PIF file. You want a particular amount of extended memory? Okay, we’ll set that up. You want a custom icon? Sure, no problem. You want it to disable DPMI memory? You got it. Once that’s all set up, the virtual MS-DOS driver says, “Okay, and set the initial CS:IP for the virtual machine to the MS-DOS EXEC call to run the program the PIF file specified.” The EXEC call executes, and the interop code kicks in and launches the 32-bit Windows program.

From the virtual machine’s point of view, nothing is actually wrong; you merely did something in a really roundabout way. It’s like booking a meeting room, specifying that you would like a slide projector, that the chairs and tables be set in a particular arrangement, that everybody be provided with water and a notebook, and then putting a sign on the door that says, “This meeting has moved to Location Z.” You go to all this effort to get the conference room to be set up exactly the way you want it, and then you end up not using it. The conference center doesn’t care (as long as it still gets paid).

PIF files are like shortcuts, but with the added effort of creating an MS-DOS virtual machine. And just like with shortcuts, bad guys can choose a dangerous target and make your day miserable.

Comments (22)
  1. kog999 says:

    seems to me the question shouldn’t be

    "why it’s possible to create a PIF file that refers to a program that isn’t an MS-DOS program"

    but instead

    "why would someone want to create a PIF file that refers to a program that isn’t an MS-DOS program"

    that would make for a more insteresting explination. If there is a valid reason to do this then why try to stop them in the first place. If there isn’t a reason then blame the programmer for wasting resources and not windows for allowing them to do it.

  2. Richard Wells says:

    Some of the PIF files that pointed to non-PIF files were ghosts of upgrades from MS-DOS to Windows versions. It would be difficult to track down every shortcut that would link to the old PIF file thus it is easier to modify the PIF file to redirect to the current Windows executable.

  3. Maurits says:

    > You can’t even enforce it at the time the PIF file is launched, because somebody could replace the file during the split second between checking the file type and actually using it.

    Does not follow.  Sure, someone could replace the file during the split second between checking the file type and actually using it – but you /could/ enforce it at the time the PIF file is launched.  The enforcement wouldn’t be ironclad, agreed, but it would (arguably) be better than nothing.

    [True, it would reduce the scope, but it wouldn’t solve the problem outright, which was my point (poorly phrased). -Raymond]
  4. No body says:

    Why can’t you modify some shortcuts that some installers put on the Start Menu folder?

  5. Brian says:

    Related to your bizarre red tape comment, I once tried renting a car (in person) and the gal at the counter informed me that the special advertised price was only available online.  So, I pulled out my internet-connected cell phone and booked the car at the reduced rate.

  6. DWalker59 says:

    Replacing a file in the split second between checking the file type and actually launching it seems like … a red herring.

    What if permissions are altered between the time they are checked and the time a file is opened?  What if a file is deleted between the time permissions are checked and actually opening it?  What if all kinds of things happen between step 1 and step 2 of any process?  The operating system can’t prevent all such occurrences.

    I don’t think that’s a huge concern; if the file is replaced, the application may crash when Windows tries to “run” it.  It’s not like this is going to happen often.

    [You can hit this with 100% certainty. Set up a malware site that responds with an MS-DOS program the first time any particular IP address opens the attack file, and responds with a Win32 program the second time. -Raymond]
  7. Random832 says:

    For that matter, what if a windows exe file is replaced with a dos (or 16-bit windows) exe in the split second between when it decides not to create a virtual machine with the default settings [as when you directly launch a dos exe] and when it actually uses it?

    [That one’s easy: The Win32 loader rejects it. -Raymond]
  8. Hadron says:

    I bet if I made a PIF file that pointed to the Higgs Boson, Windows could go back in time to stop it.

  9. drysart@gmail.com says:

    Why can’t you modify some shortcuts that some installers put on the Start Menu folder?

    You’re probably referring to Windows Installer’s advertised shortcuts.  They don’t actually point to a file, they fire off a call into Windows Installer instead, which checks to see if the target is actually installed (launching an install process if its not, or if it needs to be repaired), then launching the underlying file only after its satisfied the house is in order.

  10. porter says:

    > Now, back in the days when PIF files were invented, if you tried to run something that wasn’t an MS-DOS program inside an MS-DOS virtual machine,

    PIF files were invented before there was any virtualisation, they were there in Windows 1.0 on an 8088. From memory, the DOS exec 0x21 trap would run a windows program. You only got the WINSTUB.EXE response if windows wasn’t actually running.

  11. configurator says:

    @Miral: I remember about 10 years ago I used to make PIFs to bat files all the time for that exact reason. I remember it was quite annoying, too.

    @Raymond: "You want a custom icon? Sure, no problem." The custom icon comes up when the pif is loaded? That doesn’t seem to make sense. Am I missing something?

    Side note:

    Remember the good old days of Web 2.0 when there was this new thing called a blog with comments, and the comments actually posted when you wanted them to? I haven’t seen a site like that in a long time now.

  12. Miral says:

    @Raymond: Which is another problem, admittedly.  Which team is responsible for the shortcut property editor?  Any chance you can sneak a “close on exit” checkbox into the feature request pile?

    @configurator: Better still, comments that not only appear immediately but give you (and only you) an edit option for a few minutes even if posting without a login.  Still, I can understand why Raymond isn’t using one of those: (a) this is the standard blogs.msdn.com style — he might have to get it hosted elsewhere to get different behaviour; (b) it’s a popular blog — having immediately-shown comments would most likely get it spammed into the dark ages.  Don’t forget the trackback linkspam affair of a few months ago.

    [Um, you do realize there’s more to implementing a feature than adding a checkbox… The rules for consoles come from kernel, not the shortcut team. -Raymond]
  13. Miral says:

    PIF files actually seem to have one massive advantage over LNK files, even under Vista:

    .pif files that point at .bat files get a “Close on exit” checkbox, so you can tell them to stay open after they finish (useful to check for errors etc).

    .lnk files that point at .bat files have no such option; in order to get them to wait, every exit point from the batch file has to be protected with a “pause” command.

    Sadly, creating a shortcut to a batch file under NT/2000/XP/Vista/7 creates a .lnk, not a .pif.  (Also sadly, the .pif doesn’t work in 64-bit Windows.)

    (Of course, nowadays they *should* create .lnks.  But .lnks to console programs should have a Close on Exit checkbox.)

    [Mind you, those PIF-pointed BAT files run under COMMAND.COM, not CMD.EXE, because PIF files create MS-DOS virtual machines. -Raymond]
  14. AndyC says:

    ".lnk files that point at .bat files have no such option; in order to get them to wait, every exit point from the batch file has to be protected with a "pause" command."

    cmd /K nameofbatchfile.bat

    is your friend. :)

  15. Neil says:

    Another advantage PIF files had over LNK files on Windows 9x is that you could specify the dimensions that you wanted your console application to run in, otherwise they always opened in 50 line mode.

    On Windows XP I have the reverse problem; I can’t seem to get a DOS application to open in the dimensions I want without creating a .BAT file for it and a .LNK to the .BAT file. (All problems can be solved with indirection!)

  16. Florian says:

    A follow-up question is this: When you rename an EXE file to a PIF file, why does the program still run?

    [For the same reason an EXE renamed to COM or SCR still runs. -Raymond]
  17. Steve Hanov says:

    I like your analogies ("It’s like booking a meeting room…" Use more of them in your writing.

  18. DWalker59 says:

    @Steve: My Dad hates analogies!  "Tell me what something IS, not what it’s LIKE."  

    I’ll quote again:  Analogies are like feathers on a snake.  :-)

  19. Alexandre Grigoriev says:

    "You’re probably referring to Windows Installer’s advertised shortcuts."

    Now, if only those half-assed shortcuts were able to accept drag-drop, like the normal shortcuts do…

  20. Miral says:

    @AndyC: Actually “cmd /k” is worse, because at the end of it you get a live command prompt.

    @Raymond: Yes, of course I know that there’s more to the feature then just the checkbox.  But that’s where it starts — “users want a checkbox” -> “how do we implement that checkbox” -> “let’s get the kernel team to add something”.

    Although it ought to be doable without bothering the kernel team — if the target is a console app and “close on exit” is unchecked (or “keep open after exiting” is checked, whichever makes more sense), then the shell can create a console window for the app itself rather than letting the kernel do so on its behalf, so that the console sticks around even after the subprocess has terminated.

    [“the shell” isn’t a process; it’s a library. From Notepad, do File.Open, right-click a shortcut, select “Open”, then that console window will be opened by Notepad, and when you exit Notepad, that console window vanishes? -Raymond]
  21. Consolas says:

    The easiest way to replicate PIF-style "Close on Exit" functionality in shortcuts is to append the conditional operators || or && along with the pause command to the target.

    For example, to have the console stay open if a batch or console app fails, create a shortcut and change the target to the following:

    <path>consoleapp.exe || pause

  22. consumer4beta@hotmail.com says:

    Put NTVDM damn it under 64-bit Windows. Did MS say it was technically impossible?

Comments are closed.