Skip to main content

Build and parse Windows .lnk files (MS-SHLLINK) in Python.

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lnksmith-0.0.4.tar.gz (85.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lnksmith-0.0.4-py3-none-any.whl (39.8 kB view details)

Uploaded Python 3

File details

Details for the file lnksmith-0.0.4.tar.gz.

File metadata

  • Download URL: lnksmith-0.0.4.tar.gz
  • Upload date:
  • Size: 85.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lnksmith-0.0.4.tar.gz
Algorithm Hash digest
SHA256 743259bc7a1cd3ea43d3ec424fb7e559e72fb85716f5db8aab7cdc472e74b4c6
MD5 4198ede5502c04c430963427e9b49af9
BLAKE2b-256 cec4ca9c4b398f53f0a48cd135cb74952d86d2cfccfe7b9a73c6e6d79ba69d4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for lnksmith-0.0.4.tar.gz:

Publisher: release.yml on EuanKerr/LNKsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lnksmith-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: lnksmith-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 39.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for lnksmith-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 1d637fc3b5a6fb159b64d2970d6120f0f15f92f3d012f2835771e8d02d907f2d
MD5 57abead9acdfc5ef6fc4e8892f3a4d3b
BLAKE2b-256 951dc226424f1bf35c3509fcd9cd11ea318400fa8027573a6c12b9ccb1700e74

See more details on using hashes here.

Provenance

The following attestation bundles were made for lnksmith-0.0.4-py3-none-any.whl:

Publisher: release.yml on EuanKerr/LNKsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page