December, 2012

  • The Old New Thing

    Why was Pinball removed from Windows Vista?

    • 115 Comments

    Windows XP was the last client version of Windows to include the Pinball game that had been part of Windows since Windows 95. There is apparently speculation that this was done for legal reasons.

    No, that's not why.

    One of the things I did in Windows XP was port several millions of lines of code from 32-bit to 64-bit Windows so that we could ship Windows XP 64-bit Edition. But one of the programs that ran into trouble was Pinball. The 64-bit version of Pinball had a pretty nasty bug where the ball would simply pass through other objects like a ghost. In particular, when you started the game, the ball would be delivered to the launcher, and then it would slowly fall towards the bottom of the screen, through the plunger, and out the bottom of the table.

    Games tended to be really short.

    Two of us tried to debug the program to figure out what was going on, but given that this was code written several years earlier by an outside company, and that nobody at Microsoft ever understood how the code worked (much less still understood it), and that most of the code was completely uncommented, we simply couldn't figure out why the collision detector was not working. Heck, we couldn't even find the collision detector!

    We had several million lines of code still to port, so we couldn't afford to spend days studying the code trying to figure out what obscure floating point rounding error was causing collision detection to fail. We just made the executive decision right there to drop Pinball from the product.

    If it makes you feel better, I am saddened by this as much as you are. I really enjoyed playing that game. It was the location of the one Windows XP feature I am most proud of.

    Update: Hey everybody asking that the source code be released: The source code was licensed from another company. If you want the source code, you have to go ask them.

  • The Old New Thing

    You too can use your psychic powers: Spaces in paths

    • 29 Comments

    I'm going to be lazy today and make you solve the problem.

    Did a recent security hotfix change change the way we handle UNC paths with spaces? Normally, if we open the Run dialog and type \\server\share\Support Library\, the Support Library folder opens. But recently it stopped working. Instead of opening the Support Library folder, we get the Open With dialog:

    Open with

    Choose the program you want to use to open this file:

    File: Support

      Contoso Chess Challenger 5.0
      Contoso Music Studio
      Fabrikam Chart 2.0
      Litware 2010
    $   Woodgrove Bank Online
     
     
     
     
     
     
     
      Happy Holidays!
     
     
     
     
     
      Always use the selected program to open this kind of file

     

    Can you figure out what happened recently that introduced this problem? You have all the information you need.

  • The Old New Thing

    I'll tell you what I think of the new University of California logo once it finishes loading

    • 20 Comments
    The new University of California logo
  • The Old New Thing

    Have you found any TheDailyWTF-worthy code during the development of Windows 95?

    • 25 Comments

    Mott555 is interested in some sloppy/ugly code or strange workarounds or code comments during the development of Windows 95, like "anything TheDailyWTF-worthy."

    I discovered that opening a particular program churned the hard drive a lot when you opened it. I decided to hook up the debugger to see what the problem was. What I discovered was code that went roughly like this, in pseudo-code:

    int TryToCallFunctionX(a, b, c)
    {
      for each file in (SystemDirectory,
                        WindowsDirectory,
                        ProgramFilesDirectory(RecursiveSearch),
                        KitchenSink,
                        Uncle.GetKitchenSink)
      {
        hInstance = LoadLibrary(file);
        fn = GetProcAddress(hInstance, "FunctionX");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "__imp__FunctionX");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "FunctionX@12");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        fn = GetProcAddress(hInstance, "__imp__FunctionX@12");
        if (fn != nullptr) {
            int result = fn(a,b,c);
            FreeLibrary(hInstance);
            return result;
        }
        FreeLibrary(hInstance);
      }
      return 0;
    }
    

    The code enumerated every file in the system directory, Windows directory, Program Files directory, and possibly also the kitchen sink and their uncle's kitchen sink. It tries to load each one as a library, and sees if it has an export called FunctionX. For good measure, it also tries __imp__­FunctionX, FunctionX@12, and __imp__­FunctionX@12. If it finds any match, it calls the function.

    As it happens, every single call to Get­Proc­Address failed. The function they were trying to call was an internal function in the window manager that wasn't exported. I guess they figured, "Hm, I can't find it in user32. Maybe it moved to some other DLL," and went through every DLL they could think of.

    I called out this rather dubious programming technique, and word got back to the development team for that program. They came back and admitted, "Yeah, we were hoping to call that function, but couldn't find it, and the code you found is stuff we added during debugging. We have no intention of actually shipping that code."

    Well, yeah, but still, what possesses you to try such a crazy technique, even if only for debugging?

  • The Old New Thing

    Why do some shortcuts not support editing the command line and other properties?

    • 27 Comments

    Ben L observed that some shortcuts do not permit the command line and other options to be edited. "Where is this feature controlled? Is there a way to override this mode?" This question is echoed by "Anonymous (Mosquito buzzing around)" (and don't think we don't know who you are), who in a huge laundry list of questions adds, "Why does the Game Explorer limit customizing command line, target, etc?"

    These questions are looking at the situation backwards. The issue is not "Why do these shortcuts block editing the command line?" The issue is "Why do some shortcuts allow editing the command line?"

    Recall that shortcuts are references to objects in the shell namespace. Shell namespace objects are abstract. Some of them refer to files, but others refer to non-file objects, like control panels, printers, and dial-up networking connectoids. And in the abstract, these objects support verbs like Open and Rename. But there is no requirement that a shell namespace object support "Run with command line argument".

    If you have a shortcut to an executable, then the LNK file handler says, "Okay, this is a special case. Executables support command line arguments, so I will run the executable with the command line arguments set by the IShell­Link::Set­Arguments method.

    Note that the shortcut target and arguments are separate properties. The LNK file property sheet hides this from you by calling IShell­Link::Get­Path and IShell­Link::Get­Arguments, then taking the two strings and combining them into a single Target field for display. When you save the changes, the LNK file property sheet takes the Target, figures out which part is the executable and which part is the arguments, and calls IShell­Link::Set­Path and IShell­Link::Set­Arguments on the two parts.

    In other words, the command line is all a ruse.

    This special action is performed only for executable targets, because those are the only things that accept arguments. If you create a shortcut to a control panel, you'll find that the Target is not editable. If you create a shortcut to a printer, you'll find that the Target is not editable. If you create a shortcut to a dial-up networking connectoid, you'll find that the Target is not editable. Having a non-editable command line is the normal case. The file system is the weirdo.

    Shortcuts to advertise applications and shortcuts to items in the Games folder are not shortcuts to executables. They are shortcuts into the shell namespace for various types of virtual data. An advertised application is a shell namespace object that represents "an installed application". It is not a pointer directly to the executable, but rather a reference to an entry in the MSI database, which in turn contains information about how to install the program, repair it, update it, and run it. The shell doesn't even know what the command line is. To launch an advertised shortcut, the shell asks the MSI database for the command line, and it then executes that command line that MSI returns. The value set by IShell­Link::Set­Arguments never enters the picture. Similarly, the entries in the Games Folder are not executables; they are entries in the games database.

    I can see how this can be confusing, because when you click on these shortcuts, a program runs, but these shortcuts are not shortcuts directly to programs. As a result, the code that takes a Target and Arguments and combines them into a command line does not get a chance to run.

  • The Old New Thing

    Why is it so hard to write a program that requires UI Access privilege?

    • 23 Comments

    If you want your program to have the UI Access privilege, you have to jump through a few hoops. The program needs to be digitally signed, and it needs to go into the system32 directory. Why is it so hard to get UI Access?

    Because UI Access bypasses User Interface Privilege Isolation (UIPI) security measures. The more valuable the target, the more substantial the security measures.

    UI Access allows low-integrity programs to access and interact with the user interface of high-integrity programs. This has historically been the source of security vulnerabilities. UIPI was created in part to prevent this type of security attack. If a low-integrity program could programmatically manipulate the user interface of a high-integrity program, then all an attacker needs to do is sit and wait for the user to elevate a command prompt, and then start programmatically driving the command prompt to do whatever it wanted.

    If all you had to do to obtain UI Access was simply ask for it (by setting uiaccess="true" in your manifest), then every piece of malware would just do that, and boom, the value of UIPI has effectively vanished. (This is the sort of trap that leads to eventually, nothing is special any more.)

    Okay, so the digital signature requirement is there to create a barrier to entry for malware authors. It also creates some degree of accountability (since you have to identify yourself to a certificate authority, though as we've seen in the past, this relies on certificate authorities remaining trustworthy), And it allows your application's ability to obtain UI Access to be revoked by revoking the certificate.

    But why does the file have to be in the system32 directory?

    As we saw some time ago, the directory is the application bundle. If programs with UI Access could be installed anywhere, then an attacker could exploit an insecure application directory to plant a rogue copy of a system DLL in that directory, allowing itself to be injected into the process with UI Access and thereby compromise it.

    The thinking here is "If the application cannot create its install directory, then the application cannot create its install directory wrong."

    Requiring progams with UI Access to be installed into the system32 directory is an additional secure by default measure. In order to compromise the application bundle, the attacker must already have compromised the system32 directory, at which point he's already on the other side of the airtight hatchway.

  • The Old New Thing

    2012 year-end link clearance

    • 12 Comments

    Another round of the semi-annual link clearance.

    Snark

    Tech

    Culture (or what passes for it)

    Other Stuff

    And, as always, the obligatory plug for my column in TechNet Magazine:

  • The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Writing to the application directory

    • 25 Comments

    We received a security vulnerability report that went roughly like this:

    There is a security vulnerability in the X component. It loads shell32.dll from the current directory, thereby making it vulnerable to a current directory attack. Here is a sample program that illustrates the problem. Copy a rogue shell32.dll into the current directory and run the program. Observe that the rogue shell32.dll is loaded instead of the system one.

    If you actually followed the instructions, what you saw depended on your definition of "run the program." Let's assume that the program has been placed in the directory C:\sample\sample.exe.

    1. Setting the current directory to the application directory.
      cd /d C:\sample
      copy \\rogue\server\shell32.dll
      c:\sample\sample.exe
      
      In this case, the attack succeeds.
    2. Setting the current directory to an unrelated directory.
      cd /d %USERPROFILE%
      copy \\rogue\server\shell32.dll
      c:\sample\sample.exe
      
      In this case, the attack fails.
    3. Running the application from Explorer.
      copy \\rogue\server\shell32.dll C:\sample
      double-click sample.exe in Explorer
      
      In this case, the attack succeeds.

    Let's look at case 3 first. In case 3, what is the current directory? When you launch a program from Explorer, the current directory is set to the directory of the thing you double-clicked. Therefore, case 3 is identical to case 1. That's one less case to have to study.

    We also see that the attack is not strictly a current directory attack, because the attack failed in case 2 even though a rogue shell32.dll was in the current directory.

    What we're actually seeing is an application directory attack.

    Recall that the application directory is searched ahead of the system directory. Therefore, you can override a file in the system directory by putting it in your application directory. This is part of the directory as a bundle principle. If you packaged a DLL with your application, then presumably that's the one you want, even if a future version of Windows decides to create a DLL of the same name.

    The vulnerability report sort of acknowledged that this was an application directory attack rather than a current directory attack when they explained why this is a serious problem:

    By placing a rogue copy of shell32.dll in the C:\Program Files\Microsoft Office\Office12 directory, an attacker can inject arbitrary code into all Office applications.

    If the attack were really a current directory attack, the attacker would have put a rogue copy of shell32.dll in the directory containing your Excel spreadsheet, not the directory containing EXCEL.EXE.

    And that's where you reach the airtight hatchway: Normal users do not have write permission into the C:\Program Files\Microsoft Office\Office12 directory. You need administrator privileges to create files there. And if you have administrator privileges, then you already pwn the machine. It's not really a vulnerability that you can do anything you want once you pwn the machine.

    Of course, this non-vulnerability does expose a security issue you need to bear in mind when you run your own programs: Your application's directory is its airtight hatchway. Make sure you control who you let in! If you leave your application directory world-writeable, then you've effectively left your airtight hatchway unlocked. This is one reason why the Microsoft Logo guidelines recommend (require?) that programs be installed into the Program Files directory: The default security descriptor for subdirectories of Program Files does not grant write permission to normal users. It's secure by default.

    There are many variations of this type of vulnerability report, and they nearly always are mischaracterized as a current directory attack. They usually go like this:

    There is a DLL planting vulnerability in LITWARE.EXE. Place a rogue DLL named SHELL32.DLL in the same directory as LITWARE.EXE. When LITWARE.EXE is run, the rogue DLL is loaded from the current directory, resulting in code injection.

    The person who submits the report has confused the application directory with the current directory, probably because they never considered that the two might be different.

    C:\> mkdir C:\test
    C:\> cd C:\test
    C:\test> copy \\trusted\server\LITWARE.EXE
    C:\test> copy \\rogue\server\SHELL32.DLL
    C:\test> LITWARE
    -- observe that the rogue DLL is loaded
    -- proof of current directory attack
    

    They never tried this:

    C:\> mkdir C:\test
    C:\> cd C:\test
    C:\test> copy \\trusted\server\LITWARE.EXE
    C:\> mkdir C:\test2
    C:\> cd C:\test2
    C:\test2> copy \\rogue\server\SHELL32.DLL
    C:\test2> ..\test\LITWARE
    -- observe that the rogue DLL is not loaded
    

    That second experiment shows that the attack is not a current directory attack at all. It's an application directory attack.

    Each time one of these reports comes in, we have to perform the same evaluation to confirm that it really is an application directory attack and not a current directory attack. (This means, among other things, repeating the test on every version of Windows, and every version of LitWare, and every combination of the two, just to make sure all the possibilities have been covered. The odds are strong that it will all turn into a false alarm, but who knows. Maybe there's something about the interaction between LitWare 5.2 SP2 and Windows XP SP3 that triggers a new code path that does indeed try to load shell32.dll from the current directory. And it's that specific combination of circumstances the person was trying to report, but did a bad job of expressing.)

  • The Old New Thing

    The QuickCD PowerToy, a brief look back

    • 27 Comments

    One of the original Windows 95 PowerToys was a tool called QuickCD. Though that wasn't its original name.

    The original name of the QuickCD PowerToy was FlexiCD. You'd think that it was short for "Flexible CD Player", but you'd be wrong. FlexiCD was actually named after its author, whose name is Felix, but who uses the "Flexi" anagram as a whimsical nickname. We still called him Felix, but he would occasionally use the Flexi nickname to sign off an email message, or use it whenever he had to create a userid for a Web site (if Web sites which required user registration existed in 1994).

    You can still see remnants of FlexiCD in the documentation. The last sample INF file on this page was taken from the QuickCD installer.

  • The Old New Thing

    Miss Denmark, she is dressed as a mermaid because we couldn't secure the rights from LEGO

    • 3 Comments

    Once again, the commentary is NSFW, but once again, they so deserve it.

    Miss Universe 2012 National Costumes, Part 1 my favorite is the commentary for the Dominican Republic)
    Miss Universe 2012 National Costumes, Part 2
    Miss Universe 2012 National Costumes, Part 3 (but Venezuela wins the things on top her head category)

    By the way, here's your dress made of LEGO.

    And for completeness, because I forgot to link to it last year:

    Miss Universe 2011 National Costumes, Part 1
    Miss Universe 2011 National Costumes, Part 2

Page 1 of 3 (26 items) 123