Posts tagged with: Within Windows

The WinX Menu and its hashing algorithm

This post first appeared on Within Windows on April 4, 2012.

Last week, a reader – "Windows Fan" – tipped me off to an article on Vishal Guptas blog indicating how to customize the new WinX menu in Windows 8. (You know, the menu that appears when you right-click the lower-left Start tip.) Not happy with hacking core system files and peeling back file system security, I dug a little deeper to understand what's going on and came up with a simpler solution.

So let's start at the top. The WinX menu is a simple context menu that appears when you right-click the Start tip that appears when you squish the mouse into the lower-left corner of the screen. The purpose of the menu is not to act as a Start Menu replacement but rather as a springboard to perform advanced system functions that are slightly out of reach. For example, if you’re trying to kill a runaway system process, you will probably need quick access to Task Manager, an elevated Command Prompt, and perhaps Programs and Features to uninstall the culprit app. Launching those applications in succession via the Start Screen would be a pain in the rump.

The entries on the menu are driven by shortcut (.lnk) files present in each Group folder located at %LocalAppData%\Microsoft\Windows\WinX. But you can’t manipulate the shortcuts within or add new ones. That’s because at first invocation (e.g. a fresh boot), the menu scans for and only adds approved shortcuts. Why? Again, Microsoft doesn’t want this becoming another Start Menu or, worse, an icon landfill for installers a la Quick Launch back in Windows Vista.

But an argument could be made for that small sliver of folks who genuinely want to lightly extend the menu, perhaps with utilities such as Process Monitor and DebugView. So let’s talk about what makes an approved shortcut.

An approved shortcut – a moniker I made up – is a .lnk file that has the appropriate markings to indicate to Windows “Hey, I’m special.” The marking is a simple 4-byte hash of several pieces of information. From the .lnk itself, two points are collected:

The link’s target application path/file (e.g. C:\Games\Minecraft.exe)
The link’s target application arguments (e.g. –windowed)
The third ingredient is simply a hard-coded chunk of text, or a salt if you will, to keep things interesting. That string is, literally, “Do not prehash links. This should only be done by the user.”

With these three strings in hand, Windows then glues them together, lowercases everything, and runs them through the HashData function. But you’re probably wondering at this point, what does it compare to?

Let’s shift our focus to .lnk files. We know them as shortcuts to things. But they’re officially called Shell Links and can store a lot of information on other data objects in Windows. More specifically, they support storing a structure of data called a PropertyStoreDataBlock that acts as a container for arbitrary string or numeric key/value pairs. Yep, the “WinX hash” is stored in here. If you’re curious, the key can be defined as such:

DEFINE_PROPERTYKEY(PKEY_WINX_HASH,
0xFB8D2D7B, 0x90D1, 0x4E34, 0xBF, 0x60, 0x6E, 0xAC, 0x09, 0x92, 0x2B, 0xBF, 0x02);

So to tie it all together, Windows – the Shell specifically – iterates through the .lnk files in each GroupN folder; opens them up; pulls out and concatenates the target path, args, and an arbitrary string; then finally hashes the result. This hash is then compared with the one stored in the .lnk to determine if it’s approved. Rinse and repeat.

If you’re interested in stuffing items into that menu, I wrote a tool to mark your shortcuts as approved. (The source code is on Github, if you're interested.)

NOTE: The WinX menu doesn’t seem to handle architecture-dependent environment string expansion very well, so shortcuts to %ProgramFiles% may not work (e.g. Internet Explorer 64-bit). I suspect this is a WONTFIX given it’s not designed to work with your own shortcuts.

The WinX Menu and its hashing algorithm revisited

This post first appeared on Within Windows on June 1, 2012.

In an April post, I covered the new "Win-X" menu, named after the keyboard shortcut used to access it, and how it features a hashing algorithm to determine if a shortcut was approved for display. I also offered a tool that would sign shortcuts, upgrading them the to coveted approved status.

This won't be a regurgitation of all that again. Instead, I will simply cover some changes made to the menu in Windows 8 Release Preview. (And more importantly, offer an updated version of hashlnk!)

First of the notable changes to the WinX menu in Windows 8 Release Preview is the unfortunate removal of the Network Connections shortcut. This shortcut provided a sneaky backdoor to the legacy Network Connections area, offering immediate access to network interfaces -- you know, the very items we stumble around looking for in that abhorrent Network and Sharing Center. But on the flip side, Network Connections is becoming less and less useful, thanks to better software (e.g. Windows, network drivers/stack) and the cluttering up of pseudo-interfaces like Virtual Wifi NICs, VMware and Hyper-V virtual switches and complex VPN thingamajigs. No worries.

The more important change, however, was to its hashing algorithm that sussed out whether a shortcut was approved for display in the menu. I created a tool for folks to upgrade their own shortcut files (.lnk) however it broke with the new Windows release. Let's dig a little deeper into why.

In previous versions of Windows 8, WinX would grab a shortcut, pull out the target path and arguments, hash it, and compare with an embedded value in the shortcut. This worked great, until shortcuts with environment variables were used. (I noted this as a bug in my previous post.)

For example, let's consider a shortcut pointing to %SystemRoot%\Explorer.exe. In the process of examining the shortcut, the WinX menu would expand this path -- that is replace any variables present with values fed from the OS. On a 64-bit system, the path would likely expand to C:\Windows. In some rare cases, however, this could expand to possibly C:\Winnt or even C:\Winderz for the haters out there. (The drive letter in previous versions of the algorithm was ignored.) This means the hash could be viewed as invalid and not render in the WinX menu; that kind of runtime inconsistency just won't fly in Windows.

So it was fixed.

But how?

Nothing magic really. WinX now takes the path and runs it through a quick search and replace function. It looks for matches using OS backed "folder IDs", specifically FOLDERID_ProgramFiles, FOLDERID_System, and FOLDERID_Windows. On a typical 64-bit system, these IDs would point to the values "C:\Program Files", "C:\Windows\System32", and "C:\Windows". If a match is found, WinX strips this part of the path out and replaces it with the folder ID's GUID.

To continue our example above, %SystemRoot%\Explorer.exe would expand to C:\Windows\Explorer. Having FOLDERID_System in the path, it would then ultimately transmogrify to {F38BF404-1D43-42F2-9305-67DE0B28FC23}\Explorer.exe.

That's it.

If you want to re-sign your shortcuts to now work on Windows 8 Release Preview, I updated the hashlnk tool bringing it to 0.2.0.0. Both the binaries and code at on GitHub.

Feedback is very welcome.

The case of the broken Hello Kitty IZMO toy (Part 2 of 2)

This post first appeared on Within Windows on August 13, 2011

Recap

So, back in Part 1, I managed to find software for the obscure Hello Kitty IZMO USB toy and patched it to sort of work on Windows 7. While the toy lit up at start, it didn’t quite function correctly – that is, every time I pressed keys on the keyboard, nothing happened. (This worked just fine on my Windows XP virtual machine.)

Y U NO SEE MY KEYS?

Before I could move on, I had to figure out how this software captured keystrokes. Scanning through the executable’s imports, I came across SetWindowsHookEx. SetWindowsHook is an old school API used to tap into various system events; it supports a number of hook types including those involving the keyboard (WH_KEYBOARD) and mouse (WH_MOUSE).

I set a few breakpoints, all on calls to SetWindowsHookEx, and only one was actually used. It looked like so:

SetWindowsHookExA(WH_JOURNALRECORD, myJournalRecordProc, GetModuleHandle(NULL), 0 /* dwThreadId */);

I was puzzled by the use of WH_JOURNALRECORD here, given the toy only monitors keyboard input. Perhaps the developers, at some point, were looking to capture mouse input as well. Or maybe this was a cut/paste job. Regardless, I wasn’t going to spend time changing it. (It would have required some manual assembly writing work.) Instead I focused on the GetLastError value being returned to me -- ERROR_ACCESS_DENIED.

We need more power

Elevating the application did no good. I was stuck. Out of options at the time, I decided to disable User Account Control (UAC) on my system. The program started working, holy assembler Batman! But, I was confused – why was this thing working with UAC off, but not when elevated? It turns out, disabling UAC also has a collateral impact on the state of another Windows feature called User Interface Privilege Isolation (UIPI). Introduced back in Windows Vista days, along with UAC, UIPI acts as an insulating layer of protection for processes with higher privileges. In other words, this layer prevents the little guys like Calculator from sending special messages to security-critical processes like an elevated Command Prompt preventing a specific type of evil – shatter attacks. (This insulting layer is what prevents you from dragging files onto an elevated Notepad instance, for example.)

Additional research into UIPI led to me a blurb on MSDN explaining what breaks with UIPI turned on:

A lower privilege process cannot:

  • Perform a window handle validation of higher process privilege.
  • SendMessage or PostMessage to higher privilege application windows. These application programming interfaces (APIs) return success but silently drop the window message.
  • Use thread hooks to attach to a higher privilege process.
  • Use Journal hooks to monitor a higher privilege process.
  • Perform dynamic link-library (DLL) injection to a higher privilege process.

Okay, so I knew UIPI was the culprit here... but I thought: How do I workaround this? Or more importantly, promote the Hello Kitty application to a first class Windows citizen? After hours of stumbling around on MSDN, I came across a useful attribute you can throw into your application’s manifest – uiAccess. You may have seen a manifest before, with a segment that looked something like this:

<requestedExecutionLevel uiAccess="false" level="requireAdministrator" />

It turns out, uiAccess is a special attribute that whitelists the application, letting it pass through UIPI’s gates system-wide. (This is typically reserved for rare UI assistive technology, like screen readers.) Okay, so I created a plain manifest, set uiAccess to true, and fired up Hello Kitty.exe. Still nothing.

RTFM

The software still didn’t work, with my skim of the documentation to blame. I re-read the page, this time with a discerning eye, and came across the following warning (emphasis mine):

Important: Applications with the uiAccess flag set to true must be Authenticode signed to start properly. In addition, the application must reside in a protected location in the file system. \Program Files\ and \windows\system32\ are currently the two allowable protected locations.

I remember thinking, could they have made this more difficult? Thankfully, I already had a legit code-signing certificate ready to rock and roll. (I've signed various titles, including Geosense for Windows.) A few minutes with signtool.exe and the binary was digitally signed. I copied the relevant binaries (executable, library, sound file) to a new folder, as the instructions stated, within \Program Files (x86), crossed my fingers, and tried again. (Actually, the documentation claims Program Files\ and \System32 were the only two valid folders. This is not the case on x64 systems. Both Program Files\ and Program Files (x86)\ work in this case.)

It worked.

Summary

In this case, I:

... came across supporting software bundled with InstallShield 3.0 (16-bit executable)
... unpacked the InstallShield special cabinets manually
... virtualized Windows XP to ensure the device worked
... disassembled TenxHID.dll, to discover there was a change to Windows that affected the way we interact with HID devices
... disassembled Hello Kitty.exe to discover its use of Journal Hooks to receive keyboard/mouse input
... nearly gave up and disabled UAC on my system, revealing its impact on the application
... discovered UIPI shuts down if UAC is disabled
... discovered uiAccess whitelists applications for UIPI pass-through and requires you follow a very specific set of rules for use
... learned more about solving application compatibility problems

The case of the broken Hello Kitty IZMO toy (Part 1 of 2)

This post first appeared on Within Windows on August 9, 2011.

Getting your feet wet

A month or so ago, my girlfriend pinged me about a toy her sister had collected from a yard sale. The toy was a USB-based Hello Kitty figurine that made noise when you typed. She had plugged it into her Windows 7 PC and encountered a slight problem: It didn’t do anything. This thing needed software. After an Internet deep dive, I discovered and downloaded the drivers on Cables Unlimited cached site at about 1 kilobyte/second. I carefully extracted the ZIP and ran Setup...

incompatible

I remember experiencing a number of emotions at this point, but the only one that made an impression (on my desk) was rage. Someone had packaged the software using an old school version of InstallShield (3.0) that produces 16-bit stubs. After calming down, I decided to go ahead and rip out the binaries from its cabinet files using an equally as old tool called WinPack.

winpack

With files in hand, I was surprised at what little there was to play with. There was a documentation attempt, an icon, a little notification area program, a sound file, and a supporting DLL. I plugged the toy into the PC and ran the program. Other than putting a cutesy icon in my notification area, nothing happened. Sweet. Time to debug!

I first threw the executable into IDA Pro. It was immediately obvious it only handled UI operations. The actual work was delegated to TenxHID.dll. I then started analyzing the library. TenxHID.dll contained three exported functions (four if you count DllEntryPoint):

  • DeviceIni
  • ReadBuffer
  • WriteBuffer

Focusing first on DeviceIni, I followed the various calls around and drew a mental picture of how this thing worked. It first looked for the HID device using HidD_GetHidGuid, SetupDiGetClassDevsA, SetupDiEnumDeviceInterfaces and SetupDiGetDeviceInterfaceDetailA APIs. Then, using WriteFile, it communicated with the device over a pipe. With my debugger, I set a breakpoint on various calls to determine a] if the library was finding the device and b] if WriteFile succeeded.

Surprisingly, the library was finding the device just fine. No problems there. But WriteFile was failing, due to an invalid HANDLE (hFile) being passed in. Tracing my way backwards, I found and set a breakpoint on the related CreateFile. A re-run through the debugger confirmed CreateFile was failing with an ERROR_ACCESS_DENIED.

Whoa, hold on there

Before I continued, I decided to take a few steps back. I had broken one of my rules when dissecting software – observe the software in an operating manner first. I set this rule because more often than not, the very software I’m tinkering with doesn’t work in the intended environment, let alone mine.

I fired up VMWare and installed Windows XP. After fighting VMWare’s broken Windows 7 SP1/USB support (a story for another day), I was up and running. (Any virtualization software would have worked here, although I haven’t tested Hyper-V w/ RemoteFX and USB redirection yet.) I plugged in the device, installed the software and the device was spinning around making lots of noise. Okay, cool.

Back to digging

I shifted my focus back to why this call was failing. The call looked similar to:

CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 0, OPEN_EXISTING, 0, 0);

Although the inputs worked on Windows XP, I decided to start playing with the parameters. I set a breakpoint on CreateFile and started altering values before the call. Removing the GENERIC_READ did the trick, but why?! I couldn’t find any documentation on this but I suspect Microsoft made a tweak to the way Windows handles communication to and from HID devices. Using USBView, I verified the toy exposed two USB endpoints that were both receive-only.

Endpoint Descriptor:
bEndpointAddress:    0x81  IN
Transfer Type:       Interrupt
wMaxPacketSize:      0x0008 (8)
bInterval:           0x0A

Endpoint Descriptor:
bEndpointAddress:    0x82  IN
Transfer Type:       Interrupt
wMaxPacketSize:      0x0008 (8)
bInterval:           0x0A

So it makes sense that Windows would prevent READ operations to occur here; there isn’t an OUT endpoint available to accommodate a READ request. But I’m not sure why Microsoft wouldn’t just let ReadFile fail – the very behavior the library was looking to handle. (Insight into this change would be appreciated.)

Anyway, having confirmed the toy has no outputs I simply altered the library’s assembly (with a hex editor) and changed the flags from 0xC0000000 (GENERIC_READ | GENERIC_WRITE) to 0x40000000 (GENERIC_WRITE). I re-loaded the executable and the device spun up and made its introductory noise!

But wait, I pressed a few keys on my keyboard and nothing happened... (to be continued)