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), LOLBin proxy execution, LNK/HTA polyglots, binary padding, MotW bypass (CVE-2024-38217), NTLM hash theft, icon masquerading, tracker spoofing, and persistence techniques.

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.3.tar.gz (80.0 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.3-py3-none-any.whl (37.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: lnksmith-0.0.3.tar.gz
  • Upload date:
  • Size: 80.0 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.3.tar.gz
Algorithm Hash digest
SHA256 7faef9a201c5c81348a9be4ffcdf478dd236c449474476134089230b24da734b
MD5 ed609bef5863737cf802854dbf3cf1e8
BLAKE2b-256 40e6ba344c2bb62cb00bd6a6799b73e43c9956457374e9386cf0e3420eaf7c3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for lnksmith-0.0.3.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.3-py3-none-any.whl.

File metadata

  • Download URL: lnksmith-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 37.9 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 90ff2e5eb80b932b71a137a6d80041e243186cf0a864a2f4d8326357d7f4cfe7
MD5 5e2b956475531fbbc9ff5d48924b2d9d
BLAKE2b-256 829af48861be8b0ae2c2cbad9986d6c2b2a45c58d49261b24d7b4b943c0db641

See more details on using hashes here.

Provenance

The following attestation bundles were made for lnksmith-0.0.3-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