Files
reverse-engineering-anything/docs/guides/native/windows-shortcut.md
T
RRFZ b4c3a028fe fix(windows): leave a shortcut icon comparison unknown across code pages (#9691)
* fix(windows): leave a shortcut icon comparison unknown across code pages

Windows stores the LinkInfo LocalBasePath only as ANSI when the system
code page can represent it, while StringData stays UTF-16. The parser
projects the ANSI bytes as Latin1, so on a code page 936 host a path such
as F:\百度网盘\BaiduNetdisk\BaiduNetdisk.exe never matched the same
Unicode IconLocation, and icon_location_differs_from_target reported true
for a shortcut whose icon is its own target.

Record whether each target path is an ANSI projection. Compare it with
the icon only when both use the same encoding or the ANSI text is ASCII.
A full target that cannot be compared makes the result null, like a
%VAR% target.

* fix(windows): keep each LinkInfo part's encoding when joining paths

A joined LinkInfo target was marked ANSI when any part was ANSI. An ASCII
ANSI share with a UTF-16 suffix such as \\server\share + 工具\app.exe
then could not be compared with a Unicode icon, although no byte needs a
code page. Record which encoding each part's non-ASCII text came from,
and compare two paths when their non-ASCII text shares one encoding.
2026-11-10 15:39:04 -05:00

5.0 KiB

Windows Shell Link shortcuts

inspect_windows_shortcut / inspect-windows-shortcut answers whether one selected local file is a Windows Shell Link (.lnk), which target path, arguments, working directory, and icon location it records, which volume and network names LinkInfo stores, and which ExtraData blocks follow the strings. It reads the file without resolving or executing the target and does not require a Windows SDK, COM, or a network.

rea inspect-windows-shortcut /absolute/path/to/shortcut.lnk --json

The CLI resolves relative paths against the caller's working directory. MCP and the advertised input schema require an absolute filesystem path and preserve that exact selection:

{
  "name": "inspect_windows_shortcut",
  "arguments": { "path": "/artifacts/shortcut.lnk" }
}

Observations

The inline Evidence result contains the artifact path, SHA-256, and byte length. header is the 76-byte ShellLinkHeader: LinkFlags and FileAttributes as raw values plus documented names, creation/access/write FILETIMEs as a raw 64-bit decimal and ISO-8601 UTC when the timestamp is in range, file size, icon index, ShowCommand (normal, maximized, or minimized), and hotkey modifiers. Undocumented ShowCommand values are decoded as normal, as specified.

id_list is present when HasLinkTargetIDList is set. Each item keeps its file offset, size, and type byte. Root-folder, volume, and file-entry items are decoded when those layouts match documented shell-item headers, including the 8.3 short name on a file entry. Every other item is raw with a SHA-256 of its payload. Unknown items are not guessed.

link_info reports volume drive type, serial, label, local base path, and common network relative link names, with Unicode variants when the header declares them. ANSI strings use a byte-preserving Latin1 projection; the original system ANSI code page is unobserved.

string_data reports name, relative path, working directory, command-line arguments, and icon location according to LinkFlags, each with encoding, CountCharacters, byte length, and the decoded value. IsUnicode selects UTF-16LE; otherwise the Latin1 projection is used.

extra_data enumerates every block: signature, size, and offset. EnvironmentVariableDataBlock and IconEnvironmentDataBlock expose ANSI and Unicode targets. TrackerDataBlock exposes the NetBIOS machine id and droid / birth-droid GUIDs. Version-1 UUID MAC and timestamp values are labelled evidence_kind: "derived". KnownFolderDataBlock and SpecialFolderDataBlock keep their folder identifiers. ConsoleFEDataBlock keeps the code page. PropertyStoreDataBlock and unrecognized signatures stay raw with SHA-256. Unknown signatures are listed and are not dropped.

observations are derived only from those documented fields: whether arguments are present, argument character length, target extension, whether ShowCommand is minimized, and whether the icon location differs from the recorded target path. That comparison is null unless the icon and a recorded target are both full paths: a stored filename, relative path, or %VAR% form cannot show that two locations differ. Windows stores the LinkInfo path only as ANSI when the system code page can represent it. An ANSI path with non-ASCII bytes is therefore not compared with a Unicode icon location, or the reverse, because the code page is unobserved. This workflow does not emit verdicts about intent.

A missing optional section is observed absence of that structure. It is not proof the shortcut never carried that data in another container.

Limits and failures

The selected file is limited to 1 MiB by default (16 MiB maximum). At most 256 IDList items (4096 maximum) and 64 ExtraData blocks (1024 maximum) are examined by default. Retained string payload bytes across StringData, LinkInfo, and ExtraData are limited to 64 KiB by default (1 MiB maximum). Malformed HeaderSize or LinkCLSID, and exhausted budgets, fail without partial success. Truncation after a valid header, ExtraData size overruns, and odd Unicode lengths return partial coverage with coverage.failing_offset. A LinkInfo offset that points outside its structure is reported at the offset field itself, so every issue offset lies inside the file. Coverage is never complete when issues are present.

The selected path must be a regular file. Symbolic links are rejected. UNC paths and other host-prefixed device paths, such as \\server\share\a.lnk and \\?\UNC\server\share\a.lnk, are rejected before any filesystem call. On Windows, a path whose parent directory is a symbolic link or junction is rejected before anything follows that link. The check covers the directories Windows opens after removing . and .., so C:\alias\..\real\a.lnk is checked at C:\real only; a \\?\ path is checked as written. A mapped network drive cannot be told apart from a local drive by its path and is not rejected. This workflow does not resolve, open, or execute the link target or call COM, and it does not contact a network for a path on a local volume.