LNK Toolmarks, Revisted

There was a recent blog post and Twitter thread regarding the parsing and use of weaponized LNK file metadata. Based on some of what was shared during the exchange, I got to thinking about toolmarks again, and how such files might be created.  My thinking was that perhaps some insight could be gained from the format and structure of the file itself.  For example, the weaponized LNK files from the two campaigns appear to have valid structures, and there appear to have been no modifications to the LNK file structure itself.  Also, the files contained specific structures, including a PropertyStoreDataBlock and a TrackerDataBlock.  While this may not seem particular unusual, I have seen some LNK files that do not contain these structures.  I parsed an LNK file not long ago that did not contain a TrackerDataBlock.  As such, I thought I'd look at some ways, or at least one way, to create LNK files and see what the resulting files would "look like".

Several years ago, Adam had an excellent blog post regarding LNK hotkeys; I borrowed the VBS code (other examples and code snippets can be found here and here), and made some minor tweaks.  For example, I pointed the target path to calc.exe, ran the code, and then moved the file from the Desktop to a testing folder, changing the file extension in the process.  Running my own parser against the resulting LNK file, I found that it had a valid PropertyStoreDataBlock (containing the user SID), as well as a properly structured TrackerDataBlock.

These findings coincide with what I saw when running the parser against LNK files from both the 2016 and 2018 APT29/Cozy Bear campaigns.

You can also use PowerShell to create shortcuts, using the same API as the VBScript:
Create shortcuts in PowerShell
PowerShell script to modify an LNK file (target path)
Editing shortcuts in PowerShell

We also know that the LNK files used in those campaigns were relatively large, much larger than a 'normal' LNK file, because the logical file was extended beyond the LNK file structure to include additional payloads.  These payloads were extracted by the PowerShell commands embedded with in the LNK file itself.

Felix Weyne published a blog post that discussed how to create a booby-trapped LNK file (much like those from the APT29 campaigns) via PowerShell.

So, we have a start in understanding how the LNK files may have been created.  Let's go back and take another look at the LNK files themselves.

The FireEye blog post regarding the recent phishing campaign included an operational timeline in table 1.  From that table, the "LNK weaponized" time stamp was developed (at least in part) from the last modification DOSDate time stamp for the 'system32' folder shell item within the LNK file.  What this means is that the FireEye team stripped out and used as much of the LNK file metadata as they had available.  From my perspective, this is unusual because most write-ups I've seen regarding the use of weaponized LNK files (or really, any weaponized files) tend to give only a cursory overview of or reference to the file before moving on to the payloads. Even write-ups involving weaponized Word documents make mention of the file extension, maybe give a graphic illustrating the content, and then move on.

As described by the folks at JPCERT/CC, parsing of weaponized LNK files can give us a view into the attacker's development environment.  The FireEye team illustrated some of that by digging into the individual shell items and incorporating the embedded DOSDate time stamps in their analysis, and subsequently the operational timeline they shared in their post.

There's a little bit (quite literally, no pun intended...) more that we can tease out of the LNK file.  The VBScript that I ran to create an LNK file on my Windows 10 test system.  Figure 1 shows the "version" field (in the green box) for one of the shell items in the itemIDList from the LNK file.

Fig. 1: Excerpt from "foo" LNK file





In figure 1, the version is "0x09", which corresponds to a Windows 10 system (see section 6.5 of Joachim Metz's Windows Shell Item format specification).

Figure 2 illustrates the shell item version value (in the red box) from the approximate corresponding location in the APT29 LNK file from the 2018 campaign.

Fig. 2: Excerpt from APT29 LNK file





In figure 2, the version field is "0x08", which corresponds to Windows 7 (as well as Windows 8.0, and Windows 2008).  It may not be a lot, but as the versions of Windows continue to progress, this will have more meaning.

Finally, some things to consider about the weaponized LNK files...

All of the shell items in both LNK files have consistent extension blocks, which may indicate that they were created through some automated means, such as via an API, and not modified (by hand or by script) as a means of defense evasion.

So, what about that?  What is the effect of individual shell items, and to the entire LNK file, if modifications are made?  From figure 1, I modified the version value to read 0x07 instead of 0x09, and the shortcut performed as expected.  Modifications to weaponized LNK files such as these will very likely affect parsers, but for those within the community who wrote the parsers and understand the LNK file structure (along with associated shell item structures), such things are relatively straightforward to overcome (see my previous "toolmarks" blog post).

Final Words
Using "all the parts of the buffalo", and fully exploiting the data that you have available, is the only way that you're going to develop a full intelligence picture. Some of what was discussed in this post may not be immediately useful for, say, threat hunting within an infrastructure, but it can be used to develop a better understanding of the progression of techniques employed by actors, and provide a better understanding of what to hunt for.

Additional Reference Material
Joachim Metz's Windows Shell Item format specification
Link to reported bash and C versions of a tool to create LNK files on Linux