LNKsmith
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
Release files for lnksmith 1.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lnksmith-1.0.3.tar.gz | 85.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lnksmith-1.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 125.5 kB
Release files / lnksmith-1.0.3.tar.gz
| Download URL | lnksmith-1.0.3.tar.gz |
|---|---|
| Size | 85.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a6427b684ace6d929012d53524eb836c8b8984b475e2bdadb9087bed0347ceae
|
|
BLAKE2b-256 checksum How to use checksums |
ad152d4a37d7ac7a887fd16253c0b1d2d01b1fa874632a16751581007b4ac485
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.
Transparency logRelease files / lnksmith-1.0.3-py3-none-any.whl
| Download URL | lnksmith-1.0.3-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7e1bd9072e555f5b887c7c0b2013ffdf113110103a84274fc4a6a2f55f76cd5c
|
|
BLAKE2b-256 checksum How to use checksums |
a4865cee36c94337830b729c21e9ac773929a712594602bc3cd1e4c6239f6a67
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.
Transparency log