• The Old New Thing

    Under what conditions can SetFocus crash? Another debugging investigation

    • 5 Comments

    A customer asked, "Under what conditions can Set­Focus crash?"

    We have been going through our error reports and are puzzled by this one. The call stack is as follows:

    user32!_except_handler4
    ntdll!ExecuteHandler2@20
    ntdll!ExecuteHandler@20
    ntdll!RtlDispatchException
    ntdll!_KiUserExceptionDispatcher@8
    0x130862
    user32!UserCallWinProcCheckWow
    user32!__fnDWORD
    ntdll!_KiUserCallbackDispatcher@12
    user32!NtUserSetFocus
    contoso!DismissPopup
    

    At the point of the crash, the Dismiss­Popup function is calling Set­Focus to restore focus to a window handle that we got from an earlier call to Get­Active­Window. Is this safe? We imagine it might crash if the message handler for the window was unloaded from memory without being properly unregistered; are there any other reasons? More to the point, is there any way to avoid the problem (without fixing the root cause of the crash, which we may not be able to do, e.g. if that window was created by third-party code)?

    The full dump file can be found on <location>. The password is <xyzzy>.

    Indeed, what the customer suspected is what happened, confirmed by the dump file provided.

    The code behind the window procedure got unloaded. User­Call­Win­Proc­Check­Wow is trying to call the window procedure, but instead it took an exception. The address doesn't match any loaded or recently-unloaded module probably because it was a dynamically generated thunk, like the ones ATL generates.

    There isn't much you can do to defend against this. Even if you manage to detect the problem and avoid calling Set­Focus in this problematic case, all you're doing is kicking the can further down the road. Your program will crash the next time the window receives a message, which it eventually will. (For example, the next time the user changes a system setting and the WM_SETTING­CHANGE message is broadcast to all top-level windows, or the user plugs in an external monitor and the WM_DISPLAY­CHANGE message is broadcast to all top-level windows.)

    Basically, that other component pulled the pin on a grenade and handed it to your thread. That grenade is going to explode sooner or later. The only question is when.

    Such is the danger of giving your application an extension model that allows arbitrary third party code to run. The third party code can do good things to make your program more useful, but it can also do bad things to make your program crash.

  • The Old New Thing

    When designing your user interface, be mindful of the selection-readers

    • 36 Comments

    Occasionally, there will be a feature along the lines of "Whenever the user selects some text, we will pop up an X." And then I have to remind them about so-called selection readers.

    Selection readers are people who habitually select text in a document as they read it. It can be quite maddening looking over the shoulder of a selection reader, because you will see seemingly-random fragments of text get selected, and for those who are selection-deselection readers, the text will almost immediately get cleared. It's like the entire document is blinking with selections. (Other variations of the selection reader are the double-click reader who double-clicks words on the page, the margin-click reader who clicks in the margin, and the hover reader who merely hovers the mouse without clicking.)

    There are a number of theories behind why some people are selection readers.

    • It's a nervous habit to keep one's fingers occupied, similar to spinning a pen.
    • It marks one's place in the document.
    • It gives a sense of accomplishment as one progresses through the document.
    • It helps the eye follow the reading location in the document during a scroll operation.

    I am not a selection reader, but I do click in the document with some regularity. I do this for two reasons.

    1. To give focus to the document area, so that scrolling the mouse wheel or hitting PgDn will scroll the document text.
    2. To place the caret inside the viewport.

    The second reason needs some explanation.

    The caret is the blinking line that shows where your next typed character will be inserted. You can scroll the document so much that the caret goes out of the viewport. For example, if you never click in the document but merely scroll through it, the caret will be at the top of the document, even though you are reading page 25 of 50.

    And then you hit PgDn thinking that you're scrolling down one screen, but instead you're going to the middle of page one. Congratulations, you just lost your place and jumped backward 24 pages.

    Furthermore, there are some programs which are really twitchy about the caret. If you manage to scroll the caret off screen, they will say, "Sure, go ahead and scroll the caret off screen," but then you breathe on the program funny (say, by switching to another program, then switch back with Alt+Tab), and it says, "Whoa, your caret is waaaaay off screen! Let me help you by scrolling the caret back on screen. No need to thank me. Just helping out."

    Of course, what those programs ended up doing is ripping me from page 25 back to page one.

    That's why I consciously click in the document a few times after every scroll operation. It's not yet a habitual operation, so I will sometimes forget, and then just my luck, that's the time I accidentally hit PgDn or or Alt+Tab and get teleported backward in the document.

  • The Old New Thing

    Dubious security vulnerability: Luring somebody into your lair

    • 31 Comments

    A security report was received that went something like this:

    The XYZ application does not load its DLLs securely. Create a directory, say, C:\Vulnerable, and copy XYZ.EXE and a rogue copy of ABC.DLL in that directory. When C:\Vulnerable\XYZ.EXE is run, the XYZ program will load the rogue DLL instead of the official copy in the System32 directory. This is a security flaw in the XYZ program.

    Recall that the directory is the application bundle, The fact that the XYZ.EXE program loads ABC.DLL from the application directory rather than the System32 directory is not surprising because the ABC.DLL has been placed inside the XYZ.EXE program's trusted circle.

    But what is the security flaw, exactly?

    Let's identify the attacker, the victim, and the attack scenario.

    The attacker is the person who created the directory with the copy of XYZ.EXE and the rogue ABC.DLL.

    The victim is whatever poor sap runs the XYZ.EXE program from the custom directory instead of from its normal location.

    The attack scenario is

    • Attacker creates a directory, say, C:\Vulnerable.
    • copy C:\Windows\System32\XYZ.EXE C:\Vulnerable\XYZ.EXE
    • copy rogue.dll C:\Vulnerable\ABC.DLL
    • Convince a victim to run C:\Vulnerable\XYZ.EXE.

    When the victim runs C:\Vulnerable\XYZ.EXE, the rogue DLL gets loaded, and the victim is pwned.

    But the victim was already pwned even before getting to that point! Because the victim ran C:\Vulnerable\XYZ.EXE.

    A much simpler attack is to do this:

    • Attacker creates a directory, say, C:\Vulnerable.
    • copy pwned.exe C:\Vulnerable\XYZ.EXE
    • Convince a victim to run C:\Vulnerable\XYZ.EXE.

    The rogue ABC.DLL is immaterial. All it does is crank up the degree of difficulty without changing the fundamental issue: If you can trick a user into running a program you control, then the user is pwned.

    This is another case of if I can run an arbitrary program, then I can do arbitrary things, also known as MS07-052: Code execution results in code execution.

    Note that the real copy of XYZ.EXE in the System32 directory is unaffected. The attack doesn't affect users which run the real copy. And since C:\Vulnerable isn't on the default PATH, the only way to get somebody to run the rogue copy is to trick them into running the wrong copy.

    It's like saying that there's a security flaw in Anna Kournikova because people can create things that look like Anna Kournikova and trick victims into running it.

  • The Old New Thing

    The tadpole operators explained

    • 25 Comments

    Last time,¹ I introduced the tadpole operators. As you have probably figured out by now, it was a joke. There are no new tadpole operators.

    But the sample code works. What's going on?

    The tadpole operators are pseudo-operators, like the goes to operator or the sproing operator: They take advantage of existing language features, and come with a creative story.

    The tadpole operators exploit two's complement arithmetic and overflow.² The __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS is just a red herring.

    Start with the identity for two's complement negation

    -x = ~x + 1
    

    then move the -x to the right hand side and the ~x to the left hand side:

    -~x = x + 1
    

    If that was too fast for you, we can do it a different way: start with the identity for two's complement negation

    -x = ~x + 1
    

    subtract 1 from both sides

    -x - 1 = ~x
    

    and finally, negate both sides

    x + 1 = -~x
    

    To get the decrement tadpole operator, start with

    -x = ~x + 1
    

    and substitute x = -y:

    -(-y) = ~-y + 1
    

    subtract 1 from both sides and simplify -(-y) to y.

    y - 1 = ~-y
    

    Update: Justin Olbrantz (Quantam) and Ben Voigt provide a simpler derivation, starting with the identity for two's complement negation.

    -x = ~x + 1
    Rearrange terms ~x = -x - 1
    Let x = ~y Let x = -y
    -~y = ~(~y) + 1 ~-y = -(-y) - 1
    -~y = y + 1 ~-y = y - 1

    ¹Why didn't I post it on April 1st? Well, for one thing, April 1st is overcrowded. Second, it would have interfered with the run-up to the //build conference. And third, yesterday was a holiday in the United States, and I tend to schedule lighter fare on holidays.

    ²This means that they don't work on a machine that does not use two's complement, or one which checks overflow. Still, maybe they'll be useful if you're entering the IOCCC or some other contest which values minimal code size or obfuscation (or both).

  • The Old New Thing

    New C++ experimental feature: The tadpole operators

    • 116 Comments

    How often have you had to write code like this:

    x = (y + 1) % 10;
    x = (y + 1) * (z - 1);
    x = (wcslen(s) + 1) * sizeof(wchar_t);
    

    Since the + and - operators have such low precedence, you end up having to parenthesize them a lot, which can lead to heavily nested code that is hard to read.

    Visual Studio 2015 RC contains a pair of experimental operators, nicknamed tadpole operators. They let you add and subtract one from an integer value without needing parentheses.

    x = -~y % 10;
    x = -~y * ~-z;
    x = -~wcslen(s) * sizeof(wchar_t);
    

    They're called tadpole operators because they look like a tadpole swimming toward or away from the value. The tilde is the tadpole's head and the hyphen is the tail.

    Syntax Meaning Mnemonic
    -~y y + 1 Tadpole swimming toward a value makes it bigger
    ~-y y - 1 Tadpole swimming away from a value makes it smaller

    To enable the experimental tadpole operators, add this line to the top of your C++ file

    #define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS
    

    For example, here's a simple program that illustrates the tadpole operators.

    #define __ENABLE_EXPERIMENTAL_TADPOLE_OPERATORS 
    #include <ios>
    #include <iostream>
    #include <istream>
     
    int __cdecl main(int, char**)
    {
       int n = 3;
       std::cout << "3 + 1 = " << -~n << std::endl;
       std::cout << "(3 - 1) * (3 + 1) " << ~-n * -~n << std::endl;
       return 0;
    }
    

    Remember that these operators are still experimental. They are not officially part of C++, but you can play with them and give your feedback here learn more about them here.

  • The Old New Thing

    So you decided to call SHFileOperation from a service, at least remember to disable copy hooks

    • 11 Comments

    I noted some time ago that it is highly inadvisable to call SHFile­Operation from a service, and then I thought about it some more and concluded, it's flat-out wrong, at least in the case where you call it while impersonating.

    Now, I'm sure that my opinion won't dissuade many of you, but if you decide to do it anyway, at least disable shell copy hooks by passing the FOFX_NO­COPY­HOOKS flag to IFile­Operation::Set­Operation­Flags. (We've met this flag before.)

    By default, shell copy hooks are active during shell file operations, and this creates a number of problems when called from a service.

    First of all, those copy hooks are unlikely to be designed to handle being run in a service. (When you write your own shell extension, do you make sure it also works when run in a service?) They're probably going to try to log the file activity, possibly to a back-end service, or maybe check with a back-end service whether this file copy should be allowed, and if not, they're probably going to display a dialog box saying "The file cannot be moved/copied/deleted because I'm a mean person who hates you due to restrictions imposed by your administrator." (Or worse, they may secretly copy the file to an undisclosed location before allowing the operation through.)

    Second of all, you probably don't want those copy hooks intefering with your file operation, whatever it is. Your service is trying to clean up files, or it's moving files around for its own internal purposes, and if a copy hook showed up and blocked the operation, your service is now in a weird inconsistent state.

    Note that I still consider SHFile­Operation inadvisable from a service. I'm just trying to stop you from digging your hole any deeper than it already is.

  • The Old New Thing

    If you can set enforcement for a rule, you can set up lack of enforcement

    • 9 Comments

    One of the things you can do with an internal tool I've been calling Program Q is run a program any time somebody wants to add or modify a record. The program has wide latitude in what it can do. It can inspect the record being added/modified, maybe record side information in another table, and one of the things it can decide to do is to reject the operation.

    We have set up a validator in our main table to ensure that the widget being added or modified is priced within the approver's limit. But sometimes, there is an urgent widget request and we want to be able to bypass the validation temporarily. Is there a way to disable the validator just for a specific record, or to disable it for all records temporarily?

    If you can set up a program to validate a record, you can also set up a program to not validate a record.

    Suppose your current validator for adding a widget goes like this:

    if (record.approver.limit < record.price) {
     record.Reject("Price exceeds approver's limit");
     return;
    }
    ... other tests go here ...
    

    And say you want to be able to allow emergency requests to go through even though, say, all approvers are unavailable. Because, maybe, the widget is on fire.

    You could decide that a widget whose description begins with the word EMERGENCY is exempt from all validation, but it generates email to a special mailing list.

    if (record.description.beginsWith("EMERGENCY"))
    {
     // emergency override: send email
     // and bypass the rest of validation
     generateNotificationEmail(record);
     return;
    }
    if (record.approver.limit < record.price) {
     record.Reject("Price exceeds approver's limit");
     return;
    }
    ... other tests go here ...
    

    Of course, the EMERGENCY rule was completely arbitrary. You can come up with whatever rules you like. The point is: If you wrote the rules, you can also write the rules so that they have exceptions.

  • The Old New Thing

    When you inadvertently become a collector of something you really aren't all that into

    • 25 Comments

    As I was heading home at the end of the day, I ran into one of my colleagues who was also going home, and he was carrying a Star Wars-themed metal lunchbox similar to this one. For those who didn't grow up in the United States, these metal lunchboxes are the type of things elementary school children use to carry their lunch to school.

    I remarked, "Nice lunchbox."

    My colleague explained, "Yeah, I sort of ended up as the lunchbox guy. It started when somebody gave me a lunchbox as a semi-humorous gift, and I kept it on my shelf. Then other people saw that I had a metal lunchbox and concluded, 'Oh, he must collect metal lunchboxes,' and they started giving me metal lunchboxes. And before I knew it, I became an unwitting collector of metal lunchboxes."

    The same thing happened to a different colleague of mine. As his first birthday after he got married approached, his new in-laws asked his wife, "What does Bob like?"

    His wife shrugged. "I dunno. He kind of likes Coca-Cola?"

    That year, he got a vintage Coca-Cola serving tray. The next year, he got a Coca-Cola clock. And then Coca-Cola drinking glasses. And so on.

    Eventually, he had to ask his wife to tell her family, "Okay, you can stop now. Bob doesn't like Coca-Cola that much."

  • The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Code injection via QueueUserAPC

    • 11 Comments

    A security vulnerability report arrived that took the following form:

    The Queue­User­APC function can be used to effect an elevation of privilege, as follows:

    1. Identify a process you wish to attack.
    2. Obtain access to a thread with THREAD_SET_­CONTEXT access.
    3. Make some educated guesses as to what DLLs are loaded in that process. Start with kernel32.dll, since you're going to need it in step 5.
    4. From the attacking process, scan the memory of those DLLs looking for a backslash, followed by something that can pass for a path and file name. Such strings are relatively abundant because there are a lot of registry paths hard-coded into those binaries. Suppose you found the string \Windows NT\Current­Version\App­Compat­Flags. Even though ASLR randomizes DLL placement, the placement is consistent among all processes, so an address calculated in one process is highliy likely to be valid in all processes.
    5. Create a DLL called C:\Windows NT\Current­Version\App­Compat­Flags.dll. Put your payload in this DLL.
    6. From the attacking thread, call Queue­User­APC with the address of Load­LibraryW as the function pointer, the victim thread as the thread handle, and a pointer to the fixed string identified in part 4 as the last parameter.
    7. The next time the victim thread processes APCs, it will pass \Windows NT\Current­Version\App­Compat­Flags to the Load­LibraryW function, which will load the payload DLL, thereby effecting code injection and consequent elevation of privilege.

    Note that this attack fails if the victim thread never waits alertably, which is true of most threads.

    If you have been paying attention, the alarm bells probably went off at step 2. If you have THREAD_SET_­CONTEXT access to a thread, then you pwn that thread. There's no need to use Queue­User­APC to make the thread do your bidding. You already have enough to make the thread dance to your music. In other words, you are already on the other side of the airtight hatchway.

    Here's how: Look for a code sequence that goes

        push someregister
        call LoadLibraryW
    

    Use the ­Set­Thread­Context function to set the pushed register equal to the address of the string you found in step 4, and set the instruction pointer to the code fragment. The thread will then resume execution at the specified instruction pointer: It pushes the address of the string, and then it calls Load­LibraryW. Bingo, your DLL loads, and you didn't even have to wait for the thread to wait alertably.

    On non-x86 platforms, this is even easier: Since all other platforms use register-based calling conventions, you merely have to load the address of the string into the "first parameter" register (rcx for x64) and set the instruction pointer to the beginning of Load­LibaryW.

    By default, THREAD_SET_­CONTEXT access is granted only to the user, and never to lower integrity levels. In other words, a low IL process cannot get THREAD_SET_­CONTEXT access to a medium or high integrity thread, and a medium IL process cannot get access to a high integrity thread. This means that, by default, you can only get THREAD_SET_­CONTEXT access to threads that have equivalent permissions to what you already have, so there is no elevation.

  • The Old New Thing

    Determining programmatically whether a file was built with LAA, ASLR, DEP, or OS-assisted /GS

    • 25 Comments

    Today's Little Program parses a module to determine whether or not it was built with the following flags:

    Remember, Little Programs do little error checking. In particular, this Little Program does no range checking, so a malformed binary can result in wild pointers.

    #include <windows.h>
    #include <imagehlp.h>
    #include <stdio.h> // horrors! mixing stdio and C++!
    #include <stddef.h>
    
    class MappedImage
    {
    public:
     bool MapImage(const char* fileName);
     void ProcessResults();
     ~MappedImage();
    
    private:
     WORD GetCharacteristics();
    
     template<typename T>
     WORD GetDllCharacteristics();
    
     template<typename T>
     bool HasSecurityCookie();
    
    private:
     HANDLE file_ = INVALID_HANDLE_VALUE;
     HANDLE mapping_ = nullptr;
     void *imageBase_ = nullptr;
     IMAGE_NT_HEADERS* headers_ = nullptr;
     int bitness_ = 0;
    };
    
    bool MappedImage::MapImage(const char* fileName)
    {
     file_ = CreateFile(fileName, GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);
     if (file_ == INVALID_HANDLE_VALUE) return false;
    
     mapping_ = CreateFileMapping(file_, NULL, PAGE_READONLY,
                                  0, 0, NULL);
     if (!mapping_) return false;
    
     imageBase_ = MapViewOfFile(mapping_, FILE_MAP_READ, 0, 0, 0);
     if (!imageBase_) return false;
    
     headers_ = ImageNtHeader(imageBase_);
     if (!headers_) return false;
     if (headers_->Signature != IMAGE_NT_SIGNATURE) return false;
    
     switch (headers_->OptionalHeader.Magic) {
     case IMAGE_NT_OPTIONAL_HDR32_MAGIC: bitness_ = 32; break;
     case IMAGE_NT_OPTIONAL_HDR64_MAGIC: bitness_ = 64; break;
     default: return false;
     }
    
     return true;
    }
    
    MappedImage::~MappedImage()
    {
     if (imageBase_) UnmapViewOfFile(imageBase_);
     if (mapping_) CloseHandle(mapping_);
     if (file_ != INVALID_HANDLE_VALUE) CloseHandle(file_);
    }
    
    WORD MappedImage::GetCharacteristics()
    {
     return headers_->FileHeader.Characteristics;
    }
    
    template<typename T>
    WORD MappedImage::GetDllCharacteristics()
    {
      return reinterpret_cast<T*>(headers_)->
        OptionalHeader.DllCharacteristics;
    }
    
    template<typename T>
    bool MappedImage::HasSecurityCookie()
    {
     ULONG size;
     T *data = static_cast<T*>(ImageDirectoryEntryToDataEx(
        imageBase_, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
        &size, NULL));
     if (!data) return false;
     ULONG minSize = offsetof(T, SecurityCookie) +
                     sizeof(data->SecurityCookie);
     if (size < minSize) return false;
     if (data->Size < minSize) return false;
     return data->SecurityCookie != 0;
    }
    
    void MappedImage::ProcessResults()
    {
     printf("%d-bit binary\n", bitness_);
     auto Characteristics = GetCharacteristics();
     printf("Large address aware: %s\n",
        (Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
        ? "Yes" : "No");
    
     auto DllCharacteristics = bitness_ == 32
        ? GetDllCharacteristics<IMAGE_NT_HEADERS32>()
        : GetDllCharacteristics<IMAGE_NT_HEADERS64>();
    
     printf("ASLR: %s\n",
        (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
        ? "Yes" : "No");
     printf("ASLR^2: %s\n",
        (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA)
        ? "Yes" : "No");
     printf("DEP: %s\n",
        (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
        ? "Yes" : "No");
     printf("TS Aware: %s\n",
        (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
        ? "Yes" : "No");
    
     bool hasSecurityCookie =
        bitness_ == 32 ? HasSecurityCookie<IMAGE_LOAD_CONFIG_DIRECTORY32>()
                       : HasSecurityCookie<IMAGE_LOAD_CONFIG_DIRECTORY64>();
     printf("/GS: %s\n", hasSecurityCookie
        ? "Yes" : "No");
    }
    
    int __cdecl main(int argc, char**argv)
    {
     MappedImage mappedImage;
     if (mappedImage.MapImage(argv[1])) {
      mappedImage.ProcessResults();
     }
     return 0;
    }
    

    Let's see what happened.

    First we use the Map­Image method to load the binary and map it into memory. While we're at it, we sniff at the headers to determine whether it is a 32-bit or 64-bit binary.

    The Get­Characteristics method merely extracts the Characteristics from the File­Header. This is easy because the File­Header is the same for 32-bit and 64-bit binaries.

    The Get­Dll­Characteristics method has two versions depending on the image bitness. In both cases, it extracts the Dll­Characteristics field, but the location of the field depends on the structure.

    The Has­Security­Cookie method also has two versions depending on the image bitness. The minimum size necessary to get OS-assisted stack overflow protection is the size that encompasses the Security­Cookie member, and in order to get that extra protection, the member needs to be nonzero.

    What is OS-assisted stack overflow protection?

    First, I'm going to assume that you've read Compiler Security Checks In Depth.

    Okay, welcome back.

    In theory, /GS could be implemented entirely in application code, with no need for operating system assistance. And in fact, that's what happens when the executable is run on older versions of Windows (like Windows 98 or Windows 2000). But the module can tell the operating system, "Hey, here is where I put my security cookie," and if the operating system understands this field, then it will go in and make the security cookie even more randomer than random by mixing in some cryptographically secure random bits.

    Okay, so that's the program. Note that some of these flags are meaningless in DLLs, so be careful to interpret the output correctly.

Page 1 of 450 (4,499 items) 12345»