A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #1818  by Evilcry
 Fri Aug 06, 2010 5:15 am
Hi,

here a quick post about .lnk file format internals :)

In this post we will meet the famous .lnk file, that in the last period registered an high attention from Security Industry cause a vulnerability exploited by a rootkit.

"Windows Shell in Microsoft Windows XP SP3, Server 2003 SP2, Vista SP1 and SP2, Server 2008 SP2 and R2, and Windows 7 allows local users or remote attackers to execute arbitrary code via a crafted (1) .LNK or (2) .PIF shortcut file, which is not properly handled during icon display in Windows Explorer, as demonstrated in the wild in July 2010, and originally reported for malware that leverages CVE-2010-2772 in Siemens WinCC SCADA systems."

The exploit uses a specially crafted LNK file. This file allows the attacker to execute an arbitrary file by carefully specifying its location – the LNK file in itself does not exploit any vulnerability such as buffer overflows, for example, so it is a legitimate LNK file. The LNK file used in targeted attacks was manually crafted as some fields that are normally present, such as CreationTime, AccessTime or WriteTime are all set to 0.

Should be clear that the basical spread vector is the malicious *.lnk file, what should be heavy market is that at the actual state of art, no autorun.inf is necessary, so we have to expect a new wave of infected USB Pen Drives.


Around here there are tons of post about SCADA Infection, so I no longer repeat the same things, very well discussed in other articles, due that I'm basically a reverser, in this post I'm going to give some fast and quick note on the Structure of Lnk File Format.

lnk vulnerability is listed as CVE-2010-2568

Lnk and Pif files are used for shortcutting, so executing on a Lnk or Pif file has the same result as executing directly the file specified by the shortcut the file that is specified on the shortcut target. The vulnerability involved in Lnk essentially executes a malicious Dll in the same context of Windows Control File.

Lnk and Pif are by design a Binary Based File Format, also called Shell Link. This file as previously exposed is used to store a link target namespace referred to a link target. As we will see in the prosecution of the post, lnk does not merely store only a link, but encapsulates a variety of informations, like:

Keyboard Shortcut that can be used to callback the link
Application Behavior
Extended Comment
Extra Data Section, that offers possibility to add Optional Data
Essentially lnk Bynary File Format inherits various characteristics from the two major file formats:
CFB - Compound File Format (used by MS-Office Files)
PROPOSTORE - Property Store Binary File Format

We can manipulate this file format via COM Objects, in this case the two major interfaces are:

IShellLink
IPersistStream
IPersistFile

Like in every File Format Reverse Engineering task, one of the best approach is to perform analysis by acting like a parser that works into two levels of abstraction, that I usually call:

TopLevel Parser
DownLevel Parser
TopLevel Parser is a shot of higher hierarchies, that keep track of lower hierarchy structures. Here a shot of higher structures:

Image

ShellLinkHeader is placed at the beginning of .lnk file and provides the following informations:
Header Size
CLSID
LinkFlags
File Attributes
Creation Time
Last Access Time
Modification Time
Target Size
Icon Index
Show Command
Hotkey
Reserved1, Reserved2, Reserved3
Header Size field is 4 bytes long and must be 0x4C => 76
CLSID is 00021401-0000-0000-c000-000000000046
ShowCommand easily specifies how the Window is displayed Normal, Minimized, Maximized.
Hotkey is easly to understand, specifies the Hotkey that can be used to call the lnk

One of the most interesting field is LinkFlags, that specifies what link structures are present into the shortcut file, here the two possible values:
HasLinkTargetIDList -> value 'A'
HasLinkInfo -> value 'B'
HasName
HasRelativePath
HasWorkingDir
HasArguments
HasIconLocation
IsUnicode
ForceNoLinkInfo
HasExpString
RunInSeparateProcess
Unused
HasDarwinId
RunAsUser
etc.
One of the most important Flag is HasLinkTargetIDList that declares the presence of another important structure, LinkTargetIDList.

LinkTargetIDList is divided into two fields:

IDListSize
IDList

IDList specifies a list of ItemIDs, each ItemID contains the Effective Data. An ItemID is composed by two fields:

ItemIDSize
Data Block

IDList and associated ItemIDs are Object Identifiers necessary to locate and identify all Shell Objects, like:

Files
Directories
Servers
Workgroups
etc

Technically these Identifiers are represented by SHITEMID structure declared in Shtypes.h

typedef struct _SHITEMID {
USHORT cb;
BYTE abID[1];
} SHITEMID;

ItemID can be processed by using the interface IShellFolder or IShellLink::GetIDList() method.

The second important flag is HasLinkInfo, because declares the presence of LinkInfo structure. This structure specifies informations necessary to resolve the link target if is not found in its original location. Here the fields:

LinkInfoSize
LinkInfoHeaderSize
LinkInfoFlags
VolumeIDOffset
LocalBasePathOffset
CommonNetworkRelativeOffset
CommonNetworkRelativeLinkOffset
CommonPathSuffixOffset
LocalBasePathOffsetUnicode
CommonPathSuffixOffsetUnicode

Between the various fields one of the most interesting is the VolumeID, that specifies informations about the volume that a link target was on when link target was created.

The Third important structure is StringData that refers to a set of structures that contain path identification informations.

String Data = NameString - RelativePath - WorkingDir - CmdLineArguments - IconLocation

The last important structure, ExtraData that is appended at the end of lnk file, contains extra informations stored as Augmented Backus-Naur Form (ABNF -> rfc 5234 )

At this point we have a complete view of Shell Link binary structure, we can now how this file is used and how to manage it.

When an user executes a lnk file, Windows is going to perform a Link Resolution, essentially by using IShellLink::Resolve() method that attempts to find the target specified by the Shell Link, this operation is accomplished by using a pointer to the already seen structure IDList. When resolution fails system calls another service, called DLT ( Distributed Link Tracking and Object Identifiers ).

Should be clear that at this point lnk information carving could be performed at two level of abstraction:

Via COM Interfaces
Raw Parsing by Mapping lnk file
Via COM Interfaces can be used the methods listed here

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

IShellLink gives informations about Arguments, IDLists, Path and Working Directory.
IShellFolder gives some more detailed information on Objects and offers methods for Object Enumeration.

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

But as you can see something is missing, I'm talking about header informations, let's see how appears from an hex dump:

Image

In evidence the Header 4C bytes long, that obviously ends at offset 4C. HeaderSize is 4 bytes long, immediately after we have the 16 bytes long CLSID.

LinkFlags is immediately after CLSID, so 4bytes + 16 bytes = 20 bytes -> 0x14 is the offset of LinkFlags that's 4bytes long.

FileAttributes-> 4bytes long and starts @offset 0x18

Now we have the three file time fields stored as FILETIME Struct

CreationTime-> 8bytes long @offset 0x1C
AccessTime-> 8bytes long @offset 0x24
ModificationTime-> 8bytes long @offset 0x2C

Image

Now is trivial to build a python script, that show lnk characteristics; thanks to libforensics things are really easy, because there is a module that deals directly with Shell Link Binary Format, I'm talking about:

lf.win.shell.link module, here a quick sample that I've coded on fly, this script show header informations that are not given by COM Interfaces:
Code: Select all
+--------------------------------------------------------------------------+
# Raw LNK Parser based on LibForensics library

from optparse import OptionParser
from datetime import datetime

from lf.dec import RawIStream, ByteIStream
from lf.win.shell.link import ShellLink

def main():
    usage = "%prog lnkFileName"
    description = "Displays Header Informations of an Lnk Binary File \n"

    parser = OptionParser(usage = usage, description = description,
    version = "0.1")

    (options, args) = parser.parse_args()

    if len(args) < 1:
        print("You must specify a *.lnk file \n")
    else:
        lnk = ShellLink(RawIStream(args[0]))

        print("Header Informations on: ",args[0], "\n")

        header = lnk.header
        
        ctime = format_timestamp(header.btime)
        atime = format_timestamp(header.atime)
        mtime = format_timestamp(header.mtime)

        print("Header Size: ", header.size, "\n")
        print("CLSID: ", header.clsid, "\n")
        print("CreationTime: ", ctime, "\n")
        print("AccessTime: ", atime, "\n")
        print("ModificationTime: ", mtime, "\n")
        print("Target Size:", header.target_size, "\n")
        print("Icon Index: ", header.icon_index, "\n")

def format_timestamp(timestamp):
    if isinstance(timestamp, datetime):
        new_timestamp = timestamp.isoformat(" ")
    else:
        new_timestamp = timestamp
    # end if

    return new_timestamp

if __name__ == "__main__":
    main()
+--------------------------------------------------------------------------+
Let's now observe the hex dump structure of LinkTargetIDList:

Image

The Structure is clear we have the IDList size that specifies the whole size and successively it's specified an ItemIDSize and immediately attached the Data, and after the next [ItemIDSize][Data]

IDList can be processed and enumerated by using again LibForensics by using ShellLink's idlist.
LinkInfo can be examined by using link_info
StringData can be examined by using string_data
ExtraData can be examined by using extra_data

Here the complete informations of the malicious lnk, obtained with linkinfo.py
+---------------------------------------------------------------------+
Command Line : test.lnk
File: test.lnk

Shell Link Header
=================
Header size: 76
CLSID: 00021401-0000-0000-c000-000000000046
Creation time: 1601-01-01 00:00:00
Access time: 1601-01-01 00:00:00
Modification time: 1601-01-01 00:00:00

Target size: 0
Icon index: 0
Show command: SW_SHOWNORMAL (0x1)
Hotkey: 0:0

Link Flags:
-----------
Has link target idlist: True
Has link info: False
Has name: False
Has relative path: False
Has working directory: False
Has arguments: False
Has icon location: False
Is unicode: True
Force no link info: False
Has exp. string: False
Run in separate process: False
Has logo3 id: False
Has darwin id: False
Run as user: False
Has exp. icon: False
No pidl alias: False
Force UNC name: False
Run with shim layer: False
Force no link track: False
Enable target metadata: False
Disable link path tracking: False
Disable known folder tracking: False
Disable known folder alias: False
Allow link to link: False
Prefer environment path: False
Keep local idlist for UNC target: False

File Attributes:
----------------
Read only: False
Hidden: False
System: False
Directory: False
Archive: False
Normal: False
Temp: False
Sparse: False
Reparse point: False
Compressed: False
Offline: False
Not content indexed: False
Encrypted: False

Link Target IDList
==================
Byte count: 20
Data: b'\x1fP\xe0O\xd0 \xea:i\x10\xa2\xd8\x08\x00+'

Byte count: 20
Data: b'.\x1e \xec!\xea:i\x10\xa2\xdd\x08\x00+'

Byte count: 268
Data: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00'

Byte count: 0
Data: Not in file

+---------------------------------------------------------------------+
In red you can see the elements that constitutes evidences of the malicious nature of the lnk.

Microsoft decided to close the Specifications of Shell Link Format, this blog post is a little abstract of the structure of lnk files, with some other collateral information. Lnk need more and more analysis and research, with these informations and with the help of python scripting is also trivial to build a Lnk Fuzzer to further investigate new possible vulnerabilities.

See you to the next post,
Giuseppe 'Evilcry' Bonfa
Last edited by EP_X0FF on Sat Aug 07, 2010 3:27 am, edited 1 time in total. Reason: Color fixed :)
 #1828  by EP_X0FF
 Fri Aug 06, 2010 2:45 pm
Hi,

excellent article :)

I guess this
Byte count: 20
Data: b'\x1fP\xe0O\xd0 \xea:i\x10\xa2\xd8\x08\x00+'

Byte count: 20
Data: b'.\x1e \xec!\xea:i\x10\xa2\xdd\x08\x00+'

Byte count: 268
Data: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\x00\x00\x00'

Byte count: 0
Data: Not in file
must be in red color? Because of this
In red you can see the elements that constitutes evidences of the malicious nature of the lnk.
Regards.
 #1954  by a_d_13
 Fri Aug 13, 2010 9:01 pm
Just for reference, here are two versions of the Shell-link documentation papers that Microsoft released. The "new" one is what is currently available here. The "old" one is the previous version that has since been removed from the website ;)

Thanks,
--AD
Attachments
Old/original version.
(1.35 MiB) Downloaded 140 times
New version.
(1.28 MiB) Downloaded 1318 times