Skip to content

EuanKerr/LNKsmith

Repository files navigation

LNKsmith

PyPI

Build and parse Windows .lnk shortcut files in Python.

Implements the MS-SHLLINK specification using the standard library struct module. Runs on any platform; the resulting .lnk files are valid on Windows.

Requires Python 3.12+.

Install

pip install lnksmith

Or from source:

git clone https://github.com/EuanKerr/lnksmith.git
cd lnksmith
pip install .

Usage

Build a shortcut

lnksmith build "C:\Windows\notepad.exe" \
    -o notepad.lnk \
    --description "Notepad" \
    --icon "C:\Windows\notepad.exe" \
    --show normal

The target path is positional - no --target flag needed. The working directory is auto-derived from the target's parent (here C:\Windows) unless you override it with --working-dir.

CLI flags (common options):

Flag Description
(positional) Full Windows target path (required)
-o, --output Output file path (default: output.lnk)
-j, --from-json JSON config file (keys match build_lnk() kwargs)
--icon Icon source path (StringData)
--icon-env Icon path with %env% variables
--env-target Target path with %env% variables
--icon-index Icon resource index (default: 0)
--description Tooltip / comment text
--relative-path Relative path to target
--working-dir Start-in directory (auto-derived from target if omitted)
--arguments Command-line arguments
--show Window state: normal, maximized, minimized
--file-size Target file size in bytes
--hotkey Hotkey combo (e.g. CTRL+C, ALT+SHIFT+F5)
--creation-time CreationTime (ISO 8601 or FILETIME ticks)
--access-time AccessTime (ISO 8601 or FILETIME ticks)
--write-time WriteTime (ISO 8601 or FILETIME ticks)
--known-folder Known folder GUID or name (e.g. Desktop)
--pad-args Prepend N whitespace chars to arguments (ZDI-CAN-25373)
--pad-size Append null bytes to inflate file size (e.g. 100MB)
--append Append file content after terminal block (polyglot)
--stomp-motw MotW bypass: dot or relative (CVE-2024-38217)

JSON-only fields (via --from-json):

Advanced MS-SHLLINK fields like tracker metadata, volume info, darwin/shim blocks, special folders, network provider details, and property stores are set through a JSON config file. JSON keys match build_lnk() kwargs directly. CLI flags override JSON values when both are provided.

More build examples

Environment-variable target (resolved by Windows at launch):

lnksmith build "C:\Windows\System32\cmd.exe" \
    --env-target "%COMSPEC%" \
    --arguments "/k echo hello" \
    --show minimized \
    -o cmd.lnk

UNC network path with a mapped drive letter (via JSON config):

echo '{"network_device_name": "Z:"}' > config.json
lnksmith build "\\\\fileserver\shared\report.xlsx" \
    -j config.json \
    -o report.lnk

Custom timestamps and volume metadata (via JSON config):

{
  "volume_label": "DATA",
  "drive_serial": 3735928559,
  "tracker_machine_id": "WORKSTATION01"
}
lnksmith build "C:\Tools\app.exe" \
    --creation-time "2025-06-15T08:30:00Z" \
    --write-time "2025-06-15T09:00:00Z" \
    -j config.json \
    -o app.lnk

Hotkey binding (Ctrl+Shift+T) with a known folder:

lnksmith build "C:\Tools\terminal.exe" \
    --hotkey CTRL+SHIFT+T \
    --known-folder "Desktop" \
    -o terminal.lnk

Supported modifier names: SHIFT, CTRL, ALT. Key names: A-Z, 0-9, F1-F24, NUM LOCK, SCROLL LOCK (per MS-SHLLINK section 2.1.3). The Python API (build_lnk) accepts any VK code with a warning for non-spec values.

Icon from an environment-variable path with a custom index:

lnksmith build "C:\Program Files\MyApp\app.exe" \
    --icon-env "%ProgramFiles%\MyApp\app.exe" \
    --icon-index 1 \
    --description "My Application" \
    -o myapp.lnk

Parse a shortcut

# Human-readable output
lnksmith parse shortcut.lnk

# JSON output
lnksmith parse shortcut.lnk --json

# Multiple files
lnksmith parse *.lnk

Python API

from lnksmith import build_lnk, write_lnk, parse_lnk, format_lnk

# Build and write a .lnk file
write_lnk("notepad.lnk", target=r"C:\Windows\notepad.exe",
           description="Notepad", working_dir=r"C:\Windows")

# Build to bytes (useful for sending over a network, embedding, etc.)
data = build_lnk(target=r"C:\Windows\System32\cmd.exe",
                 arguments="/k whoami", show_command=7)

# Parse from a file path or raw bytes
info = parse_lnk("notepad.lnk")
print(info.target_path)       # C:\Windows\notepad.exe
print(info.description)       # Notepad
print(info.working_dir)       # C:\Windows

# Human-readable dump
print(format_lnk(info))

# JSON-friendly dict
from dataclasses import asdict
print(asdict(info))

Red Team Usage

See docs/redteam.md for offensive tradecraft patterns including argument padding (ZDI-CAN-25373 / CVE-2025-9491), LOLBin proxy execution, LNK/HTA polyglots, binary padding, MotW bypass (CVE-2024-38217), NTLM hash theft, target path spoofing (Beukema Variants 0/1/4), icon masquerading, tracker spoofing, and persistence techniques.

Target path spoofing techniques are based on Wietze Beukema's "Trust Me, I'm A Shortcut" research and the lnk-it-up tool.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages