Parsing the Cozy Bear LNK File
November 2018 saw a Cozy Bear/APT29 campaign, discussed in FireEye's blog post regarding APT29 activity (from 19 Nov 2018), as well as in this Yoroi blog regarding the Cozy Bear campaign (from 21 Nov 2018). I found this particular campaign a bit fascinating, as it is another example of actors sending LNK files to their target victims, LNK files that had been created on a system other than the victim's.
However, one of the better (perhaps even the best) write-up regarding the LNK file deployed in this campaign is Oleg's description of his process for parsing that file. His write-up is very comprehensive, so I won't steal any of his thunder by repeating it here. Instead, I wanted to dig just a bit deeper into the LNK file structure itself.
Using my own parser, I extracted metadata from the LNK file structure for the "ds7002.lnk" file. The TrackerDataBlock includes much of the same information that Oleg uncovered, including the "machine ID", which is a 16-byte field containing the NetBIOS name of the system on which the LNK file was created:
***TrackerDataBlock***
Machine ID : user-pc
New Droid ID Time : Thu Oct 6 17:03:04 2016 UTC
New Droid ID Seq Num : 13273
New Droid Node ID : 08:00:27:92:24:e5
Birth Droid ID Time : Thu Oct 6 17:03:04 2016 UTC
Birth Droid ID Seq Num: 13273
Birth Droid Node ID : 08:00:27:92:24:e5
From the TrackerDataBlock, we can also see one of the MAC addresses recognized by the system. Using the OUI lookup tool from Wireshark, we see that the OUI for the displayed MAC address points to "PcsCompu PCS Computer Systems GmbH". From WhatsMyIP, we get "Pcs Systemtechnik Gmbh".
Further, there's a SID located in the PropertyStoreDataBlock:
***PropertyStoreDataBlock***
SID: S-1-5-21-1764276529-1526541935-4264456457-1000
Finally, there's the volume serial number embedded within the LNK file:
vol_sn C4B2-BD1C
A combination of the volume serial number, maching ID, and the SID from the PropertyStoreDataBlock can be used to create a Yara rule, which can then be submitted as a retro-hunt on VirusTotal, in order to locate other examples of LNK files created on this system.
Note that the FireEye write-up mentions a previous campaign (described by Volexity) in which a similar LNK file was used. In that case, MAC address, SID, and volume serial number were identical to the ones seen in the LNK file in the Nov 2018 campaign. The file size was different, and the embedded PowerShell command was different, but the rest of the identifying metadata remained the same two years later.
Another aspect of the LNK file from the Nov 2018 campaign is the embedded PowerShell command. As Oleg pointed out, the PowerShell command itself is encoded, as a base64 string. Or perhaps more accurately, a "base" + 0x40 encoded string. The manner by which commands are obfuscated can be very telling, and perhaps even used as a means for tracking the evolution of the use of the technique.
This leads to another interesting aspect of this file; rather than using an encoded PowerShell command to download the follow-on payload(s), those payloads are included encoded within the logical structure of the file itself. The delivered LNK file is over 400K in size (the LNK file from 2016 was over 660K), which is quite unusual for such a file, particularly given that the LNK file structure itself ends at offset 0x0d94, making the LNK file 3476 bytes in size.
Oleg did a great job of walking through the collection, parsing and decoding/decryption of the embedded PDF and DLL files, as well as of writing up and sharing his process. From a threat intel perspective, identifying information extracted from file metadata can be used to further the investigation and help build a clearer intel picture.
Addendum, 31 Dec: Here's a fascinating tweet thread regarding using DOSDate time stamps embedded in shellitems to identify "weaponization time" of the LNK file, and here's more of that conversation.
However, one of the better (perhaps even the best) write-up regarding the LNK file deployed in this campaign is Oleg's description of his process for parsing that file. His write-up is very comprehensive, so I won't steal any of his thunder by repeating it here. Instead, I wanted to dig just a bit deeper into the LNK file structure itself.
Using my own parser, I extracted metadata from the LNK file structure for the "ds7002.lnk" file. The TrackerDataBlock includes much of the same information that Oleg uncovered, including the "machine ID", which is a 16-byte field containing the NetBIOS name of the system on which the LNK file was created:
***TrackerDataBlock***
Machine ID : user-pc
New Droid ID Time : Thu Oct 6 17:03:04 2016 UTC
New Droid ID Seq Num : 13273
New Droid Node ID : 08:00:27:92:24:e5
Birth Droid ID Time : Thu Oct 6 17:03:04 2016 UTC
Birth Droid ID Seq Num: 13273
Birth Droid Node ID : 08:00:27:92:24:e5
From the TrackerDataBlock, we can also see one of the MAC addresses recognized by the system. Using the OUI lookup tool from Wireshark, we see that the OUI for the displayed MAC address points to "PcsCompu PCS Computer Systems GmbH". From WhatsMyIP, we get "Pcs Systemtechnik Gmbh".
Further, there's a SID located in the PropertyStoreDataBlock:
***PropertyStoreDataBlock***
SID: S-1-5-21-1764276529-1526541935-4264456457-1000
Finally, there's the volume serial number embedded within the LNK file:
vol_sn C4B2-BD1C
A combination of the volume serial number, maching ID, and the SID from the PropertyStoreDataBlock can be used to create a Yara rule, which can then be submitted as a retro-hunt on VirusTotal, in order to locate other examples of LNK files created on this system.
Note that the FireEye write-up mentions a previous campaign (described by Volexity) in which a similar LNK file was used. In that case, MAC address, SID, and volume serial number were identical to the ones seen in the LNK file in the Nov 2018 campaign. The file size was different, and the embedded PowerShell command was different, but the rest of the identifying metadata remained the same two years later.
Another aspect of the LNK file from the Nov 2018 campaign is the embedded PowerShell command. As Oleg pointed out, the PowerShell command itself is encoded, as a base64 string. Or perhaps more accurately, a "base" + 0x40 encoded string. The manner by which commands are obfuscated can be very telling, and perhaps even used as a means for tracking the evolution of the use of the technique.
This leads to another interesting aspect of this file; rather than using an encoded PowerShell command to download the follow-on payload(s), those payloads are included encoded within the logical structure of the file itself. The delivered LNK file is over 400K in size (the LNK file from 2016 was over 660K), which is quite unusual for such a file, particularly given that the LNK file structure itself ends at offset 0x0d94, making the LNK file 3476 bytes in size.
Oleg did a great job of walking through the collection, parsing and decoding/decryption of the embedded PDF and DLL files, as well as of writing up and sharing his process. From a threat intel perspective, identifying information extracted from file metadata can be used to further the investigation and help build a clearer intel picture.
Addendum, 31 Dec: Here's a fascinating tweet thread regarding using DOSDate time stamps embedded in shellitems to identify "weaponization time" of the LNK file, and here's more of that conversation.