mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 11:13:21 +00:00
* 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.
98 lines
5.0 KiB
Markdown
98 lines
5.0 KiB
Markdown
# 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.
|
|
|
|
```bash
|
|
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:
|
|
|
|
```json
|
|
{
|
|
"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.
|