A nearly year ago, a critical Windows Shell vulnerability was found in the wild (stuxnet & co), making it possible for an attacker to execute arbitrary code on a victim’s computer, by getting the user to list a directory which would contain a specially crafted .LNK file. The sole purpose of files of that type is to provide shortcut functionality – i.e. allow the user to reference various system resources (most often – executable files) through link files, instead of using the full path of the resource. Since EXPLORER.EXE makes every effort to make it even easier for the user to recognize the resource being pointed at, it displays the original resource icon (if any) as the shortcut’s one. In order to obtain the picture in the first place, the Windows Shell would sometimes call LoadLibrary on the referenced module, which would result in the execution of the library’s standard DllMain routine. What should be noted, is that LoadLibrary was usually called on legitimate Control Panel executables, but it turned out that the LNK format allowed to specify virtually any PE image as a CP module, resulting in immediate and 100% reliable execution of potentially malicious code.
What I would like to present today, is a low-impact flaw found in the LNK-parsing routines present in the SHELL32.DLL module, extensively used by EXPLORER.EXE. Exploiting this issue might result in – at most – Denial of Service conditions, or disclosure of random heap bytes from the Windows Shell process memory (which is not a big deal, considering that the user can read EXPLORER.EXE memory, anyway).
A complete specification of the Shell Link file format is available through MSDN (see [MS-SHLLINK] Shell Link (.LNK) Binary File Format). Interestingly, the document has disappeared from the Microsoft servers soon after the public announcement and wide-spread analysis of the .LNK vulnerability, but has been apparently made public, since then. To make a long story short, valid LNK files typically consist of a header structure (called SHELL_LINK_HEADER), and a list of descriptor structures, containing various shortcut characteristics. The definition of one, particular structure we are most interested in, is as follows:
Upon accessing a shortcut, SHELL32 tries to load the target path (specified by the szName string). After looking up several locations and eventually failing, the library then forms a failure message similar to the following: “%s cannot be found”, with szDisplay being the format parameter. What’s interesting, the szDisplay contents are used, even if no message box is actually displayed, i.e. during directory listing.
The offsDispName and offsComment values are supposed to store information about the beginning of the szDisplay and szComment strings (expressed either in bytes, or wide characters), relative to the beginning of the tagPIDLCPanelStruct structure. Due to the fact that no bounds checks are performed in order to verify whether these values fit in the size of the current ItemID (or even the general file length), it is possible to get the SHELL32.DLL library to execute an out-out-bounds READ operation, resulting in potential application crash. The faulty code resides within the SHELL32!CControlPanelFolder::GetDisplayName and SHELL32!CControlPanelFolder::GetDescription routines, or more precisely, the following assembly snippets:
Depending on several factors, such as the current process heap layout, the victim application may crash, due to an invalid memory reference exception (STATUS_ACCESS_VIOLATION), or make use of unspecified data, residing outside the legal bounds (current ItemID heap allocation). A shortened, exemplary crash log, generated upon listing a folder with the faulty LNK is presented below:
SHLWAPI!StrCpyNXW+19 001b:77f66730 668b01 mov ax,word ptr [ecx] EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 77f66730 (SHLWAPI!StrCpyNXW+0x00000019) ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter: 00000000 Parameter: 00171fc6 Attempt to read from address 00171fc6 STACK_TEXT: 015ee350 77f66776 015ee39c 00171fc6 00000104 SHLWAPI!StrCpyNXW+0x19 015ee364 7cb05006 015ee39c 00171fc6 00000104 SHLWAPI!StrCpyNW+0x13 015ee378 7ca538f2 00151fb0 015ee39c 00000104 SHELL32!CControlPanelFolder::GetDisplayName+0x27 015ee5a8 7c9f1ce9 000f0d80 00151fb0 00008000 SHELL32!CControlPanelFolder::GetDisplayNameOf+0x5e 015ee7e0 7c9ec806 00141180 00151fb0 00008000 SHELL32!CRegFolder::GetDisplayNameOf+0xdc 015ee904 7c9f103e 00141180 00151fb0 00008000 SHELL32!DisplayNameOf+0x29 015eeb58 7c9f0fc2 00151f88 015eeb90 00000002 SHELL32!SHGetPathFromIDListEx+0x7a 015eeb6c 7ca0d103 00151f88 015eeb90 000e4d88 SHELL32!SHGetPathFromIDListW+0x12 015eed9c 7ca0d061 015eedd4 015eefe0 7ca02f20 SHELL32!CShellLink::_LoadFromFile+0x97 015eeda8 7ca02f20 0010c2f4 015eedd4 00000000 SHELL32!CShellLink::Load+0x1e 015eefe0 7ca031f3 000e4d88 025b1478 00000000 SHELL32!CFSFolder::_HandlerCreateInstance+0x7e 015ef298 7ca0321a 000e4d88 00000000 7c9c5178 SHELL32!CFSFolder::_LoadHandler+0xcf 015ef4d8 7ca039bc 000e4d88 11021fff 7c9c809c SHELL32!CFSFolder::_CreatePerInstanceDefExtIcon+0x70 015ef72c 7ca0394d 000e4d88 7c9c809c 015ef7b0 SHELL32!CFSFolder::_CreateDefExtIcon+0x75 015ef740 7c9f2c1d 00000000 015ef7b4 00000001 SHELL32!CFSFolder::_GetExtractIcon+0x13 015ef774 7c9f3bc7 000d2f80 00000000 00000001 SHELL32!CFSFolder::GetUIObjectOf+0x21c 015ef7a4 7c9f65f3 000d2f80 00000000 000e4d88 SHELL32!SHGetIconFromPIDL+0x77 015efe20 7ca02d12 000d2f84 000e4d88 00000000 SHELL32!CFSFolder::GetIconOf+0x24e 015efe40 7ca05d9c 000d2f80 000d2f84 000e4d88 SHELL32!SHGetIconFromPIDL+0x20 015efe68 7c9f31d5 001646b0 00141610 000ebe30 SHELL32!CGetIconTask::RunInitRT+0x47
And… yes, this is pretty much it. Due to the nature of the vulnerability, a potential attacker can either crash the Windows Shell (or any other application making use of SHELL32.DLL), or get the program to reference some trash bytes from successive heap allocations. Most notably, the vulnerability can be triggered remotely (via network shares), and can also be made persistent (by placing the malicious LNK file on the desktop). Furthermore, Gynvael Coldwind has suggested that such types of security flaws (including this one) might be a nice exploitation vector, in the context of Carpet Bombing issues, e.g. when an attacker would be able to store arbitrary files on the desktop through a specially crafted website and buggy web browser, without the user’s knowledge / interaction.
A Proof-of-Concept Shell Link can be downloaded from here (p0c.lnk, 244 bytes).
To my best knowledge, the PoC is compatible with all modern Windows NT-family systems. Since the MSRC team did not consider the bug worth spending time on (agreed), it can still be used to annoy your colleagues. Enjoy, and watch out for the incoming Hack In The Box Magazine #6!