Dissecting a Shortcut

Ever wondered about the layout of shortcut files? Those tiny little buggers with the extension LNK you have probably dozens of on your desktop? For years the format was subject to reverse engineering and speculation. Last year Microsoft finally released an official format specification, documenting this surprisingly complex format. This article is the result of analyzing a typical LNK file with the help of Microsoft’s documentation and information from other sources.

The shortcut points to a copy of notepad.exe stored in “C:\Programme\Testordner”. The shortcut was created with Explorer on a German installation of Windows XP.

=====        <  Start of header (ShellLinkHeader)
4C 00 00 00  <  HeaderSize: 0x4C = 76 bytes
01 14 02 00  <  LinkCLSID: always 00021401-0000-0000-C000-000000000046
00 00 00 00  <    "
C0 00 00 00  <    "
00 00 00 46  <    "
9B 00 00 00  <  LinkFlags: 0x9B = 10011011 = HasLinkTargetIDList + HasLinkInfo + HasRelativePath + HasWorkingDir + IsUnicode
20 00 00 00  <  FileAttributes: 0x20 = 00100000 = Archive
8C 05 B9 C6  <  CreationTime: 0x01CC63D6C6B9058C = Friday, August 26, 2011 11:59:00am (as per http://www.silisoftware.com/tools/date.php)
D6 63 CC 01  <    "
B7 AD 6F CD  <  AccessTime: 0x01CC63D6CD6FADB7 = Friday, August 26, 2011 11:59:11am
D6 63 CC 01  <    "
00 A0 A1 10  <  WriteTime: 0x01C89E2710A1A000 = Monday, April 14, 2008 2:00:00pm
27 9E C8 01  <    "
00 12 01 00  <  FileSize: 0x011200 = 70,144 bytes
00 00 00 00  <  IconIndex: 0
01 00 00 00  <  ShowCommand: 1 = SW_SHOWNORMAL
00 00        <  HotKey (2 bytes): 0 = no hotkey defined
      00 00  <  Reserved1 (2 bytes)
00 00 00 00  <  Reserved2
00 00 00 00  <  Reserved3
=====        <  End of header
=====        <  Start of LinkTargetIDList (HasLinkTargetIDList indicates presence of this structure)
FD 00        <  IDListSize: 0xFD = 253 bytes
-----        <  Start of IDList structure
-----        <  Start of ItemID structure
      14 00  <  ItemIDSize: 0x14 = 20 bytes
1F           <  Type indicator: 0x1F = folder
   50        <  Folder ID: 0x50 = My Computer
      E0 4F  <  Folder GUID: 20d04fe0-3aea-1069-a2d8-08002b30309d = My Computer
D0 20 EA 3A  <    "
69 10 A2 D8  <    "
08 00 2B 30  <    "
30 9D        <    " 
-----        <  End of ItemID structure
-----        <  Start of ItemID structure
      19 00  <  ItemIDSize: 0x19 = 25 bytes
2F           <  Type indicator: 0x2F = volume name
   43 3A 5C  <  Volume name: C:\
00 00 00 00  <    "
00 00 00 00  <    "
00 00 00 00  <    "
00 00 00 00  <    "
00 00 00     <    "
-----        <  End of ItemID structure
-----        <  Start of ItemID structure
         42  <  ItemIDSize: 0x42 = 66 bytes
00           <    "
   31        <  Type indicator: 0x31 = file entry
      00     <  Flags
         00  <  File size
00 00 00     <    "
         95  <  Last modification timestamp in DOS format: 0x45B83E95 = 01000 101101 11000 0011111 0100 10101 = 21.08.2011 8:47:24
3E B8 45     <    "
         11  <  File/directory attributes: 0x11 = FILE_ATTRIBUTE_DIRECTORY + FILE_ATTRIBUTE_READONLY
00           <    "
   50 52 4F  <  Short name: PROGRA~1
47 52 41 7E  <    "
31 00 00     <    "
         2A  <  Extension size: 0x2A = 42 bytes
00           <    "
   03 00     <  Extension version: 3 = Windows XP
         04  <  Unknown
00           <    "
   EF BE     <  Unknown (0xBEEF)
         95  <  Creation timestamp in DOS format: 0x40F63E95 = 01000 000111 10110 0011111 0100 10101 = 21.08.2011 8:07:22
3E F6 40     <    "
         1A  <  Last access timestamp in DOS format: 0x4F313F1A = 01001 111001 10001 0011111 1000 11010 = 26.8.2011 9:57:17
3F 31 4F     <    "
         14  <  Unknown
00 00 00     <    "
         50  <  Long name: Programme
00 72 00 6F  <    "
00 67 00 72  <    "
00 61 00 6D  <    "
00 6D 00 65  <    "
00 00 00     <    "
         18  <  Unknown (0x18 = directory)
00           <    "
-----        <  End of ItemID structure
-----        <  Start of ItemID structure
   44 00     <  ItemIDSize: 0x44 = 68 bytes
         31  <  Type indicator: 0x31 = file entry
00           <  Flags
   00 00 00  <  File size
00           <    "
   1A 3F 59  <  Last modification timestamp in DOS format
4F           <    "
   10 00     <  Attributes: 0x10 = FILE_ATTRIBUTE_DIRECTORY
         54  <  Short name: TESTOR~1
45 53 54 4F  <    "
52 7E 31 00  <    "
00           <    "
   2C 00     <  Extension size: 0x2C = 44 bytes
         03  <  Extension version: 0x03 = Windows XP
00           <    "
   04 00     <  Unknown
         EF  <  Unknown (0xBEEF)
BE           <    "
   1A 3F 59  <  Creation timestamp in DOS format
4F           <    "
   1A 3F 59  <  Last access timestamp in DOS format
4F           <    "
   14 00 00  <  Unknown
00           <    "
   54 00 65  <  Long name: Testordner
00 73 00 74  <    "
00 6F 00 72  <    "
00 64 00 6E  <    "
00 65 00 72  <    "
00 00 00     <    "
         18  <  Unknown
00           <    "
-----        <  End of ItemID structure
-----        <  Start of ItemID structure
   48 00     <  ItemIDSize: 0x48 = 72 bytes
         32  <  Type indicator: 0x32 = file entry
00           <  Flags
   00 12 01  <  File size: 0x11200 = 70,144 bytes
00           <    "
   8E 38 00  <  Last modification timestamp in DOS format
60           <    "
   20 00     <  Attributes: 0x20 = FILE_ATTRIBUTE_ARCHIVE
         6E  <  Short name: notepad.exe
6F 74 65 70  <    "
61 64 2E 65  <    "
78 65 00     <    "
         2E  <  Extension size: 0x2E = 46 bytes
00           <    "
   03 00     <  Extension version: 0x03 = Windows XP
         04  <  Unknown
00           <    "
   EF BE     <  Unknown (0xBEEF)
         1A  <  Creation timestamp in DOS format
3F 60 4F     <    "
         1A  <  Last access timestamp in DOS format
3F 60 4F     <    "
         14  <  Unknown
00 00 00     <    "
         6E  <  Long name: notepad.exe
00 6F 00 74  <    "
00 65 00 70  <    "
00 61 00 64  <    "
00 2E 00 65  <    "
00 78 00 65  <    "
00 00 00     <    "
         1A  <  Unknown (0x18 = file)
00           <    "
-----        <  End of ItemID structure
   00 00     <  TerminalID: indicating the end of the structure
-----        <  End of ID list structure
=====        <  End of LinkTargetIDList
=====        <  Start of LinkInfo (HasLinkInfo indicates presence of this structure)
         52  <  LinkInfoSize: 0x52 = 82 bytes
00 00 00     <    "
         1C  <  LinkInfoHeaderSize: 0x1C = 28 = 'offsets to the optional fields are not specified'
00 00 00     <    "
         01  <  LinkInfoFlags: 1 = VolumeID and LocalBasePath fields are present
00 00 00     <    "
         1C  <  VolumeIDOffset: 0x1C = 28 bytes
00 00 00     <    "
         2D  <  LocalBasePathOffset: 0x2D = 45 bytes
00 00 00     <    "
         00  <  CommonNetworkRelativeLinkOffset: 0 because LinkInfoFlags does not indicate presence
00 00 00     <    "
         51  <  CommonPathSuffixOffset: 0x51 = 81 bytes
00 00 00     <    "
-----        <  Start of VolumeID structure
         11  <  VolumeIDSize: 0x11 = 17 bytes
00 00 00     <    "
         03  <  DriveType: 0x3 = DRIVE_FIXED
00 00 00     <    "
         14  <  DriveSerialNumber: 0x688E9914
99 8E 68     <    "
         10  <  VolumeLabelOffset: 0x10 = 16 bytes
00 00 00     <    "
         00  <  Volume label: empty string
-----        <  End of VolumeID structure
43 3A 5C 50  <  LocalBasePath: C:\Programme\Testordner\notepad.exe
72 6F 67 72  <    "
61 6D 6D 65  <    "
5C 54 65 73  <    "
74 6F 72 64  <    "
6E 65 72 5C  <    "
6E 6F 74 65  <    "
70 61 64 2E  <    "
65 78 65 00  <    "
00           <  CommonPathSuffix: empty string
=====        <  End of LinkInfo
=====        <  Start of RELATIVE_PATH structure (presence indicated by HasRelativePath)
   29 00     <  CountCharacters: 0x29 = 41 Unicode characters (IsUnicode is enabled)
         2E  <  Relative path (not null-terminated): ..\..\..\Programme\Testordner\notepad.exe
00 2E 00 5C  <    "
00 2E 00 2E  <    "
00 5C 00 2E  <    "
00 2E 00 5C  <    "
00 50 00 72  <    "
00 6F 00 67  <    "
00 72 00 61  <    "
00 6D 00 6D  <    "
00 65 00 5C  <    "
00 54 00 65  <    "
00 73 00 74  <    "
00 6F 00 72  <    "
00 64 00 6E  <    "
00 65 00 72  <    "
00 5C 00 6E  <    "
00 6F 00 74  <    "
00 65 00 70  <    "
00 61 00 64  <    "
00 2E 00 65  <    "
00 78 00 65  <    "
00           <    "
=====        <  End of RELATIVE_PATH structure
=====        <  Start of WORKING_DIR structure (presence indicated by HasWorkingDir)
   17 00     <  CountCharacters: 0x17 = 23 Unicode characters (IsUnicode is enabled)
         43  <  Working directory (not null-terminated): C:\Programme\Testordner
00 3A 00 5C  <    "
00 50 00 72  <    "
00 6F 00 67  <    "
00 72 00 61  <    "
00 6D 00 6D  <    "
00 65 00 5C  <    "
00 54 00 65  <    "
00 73 00 74  <    "
00 6F 00 72  <    "
00 64 00 6E  <    "
00 65 00 72  <    "
00           <    "
=====        <  End of WORKING_DIR structure
=====        <  Start of ExtraData
-----        <  Start of extra data block
   10 00 00  <  BlockSize: 0x10 = 16 bytes
00           <    "
   05 00 00  <  BlockSignature: 0xA0000005 = This block is a SpecialFolderDataBlock
A0           <    "
   26 00 00  <  SpecialFolderID: 0x26 = 38 = CSIDL_PROGRAM_FILES
00           <    "
   6F 00 00  <  Offset: 0x6F = 111. Location of this special folder in IDList
00           <    "
-----        <  End of extra data block
-----        <  Start of extra data block
   60 00 00  <  BlockSize: 0x60 = 96 bytes
00           <    "
   03 00 00  <  BlockSignature: 0xA000000003 = This block is a TrackerDataBlock
A0           <    "
   58 00 00  <  Length: must be >= 0x58
00           <    "
   00 00 00  <  Version: must be 0
00           <    "
   6D 61 63  <  MachineID (16 bytes): machinede10. NetBIOS name of the computer the link target is stored on.
68 69 6E 65  <    "
64 65 31 30  <    "
00 00 00 00  <    "
00           <    "
   5C 09 DE  <  Droid: 2 GUIDs, used to find the link target with the Link Tracking service.
4B 85 9C 8E  <    "
47 93 20 9D  <    "
B9 5D 86 6D  <    "
FE D3 FC 9E  <    "
8A 08 CF E0  <    "
11 94 8B 00  <    "
15 5D 17 7D  <    "
6F           <    "
   5C 09 DE  <  DroidBirth: 2 GUIDs, used to find the link target with the Link Tracking service.
4B 85 9C 8E  <    "
47 93 20 9D  <    "
B9 5D 86 6D  <    "
FE D3 FC 9E  <    "
8A 08 CF E0  <    "
11 94 8B 00  <    "
15 5D 17 7D  <    "
6F           <    "
-----        <  End of extra data block
   00 00 00  <  TerminalBlock: indicates end of structure
00           <    "
=====        <  End of ExtraData

References

Microsoft’s official documentation of the LNK file format
MSDN page about shell links and shortcuts
Inofficial LNK file format documentation obtained by reverse engineering
Inofficial Windows Shell Item Format Specification

, , , , ,

One Response to Dissecting a Shortcut

  1. PacMani March 16, 2013 at 18:19 #

    Thank you pretty much for an example dissection. It will be useful for my shortcut reader and writer completely written in .NET, since creating a link with .NET is a COM or p/invoke story at the moment.

Leave a Reply