EricZimmerman / EricZimmerman/LECmd

JSON/CSV output omits EnvironmentVariableDataBlock contents — target is unrecoverable for some LNKs

Open
#15 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
347
Forks
33
PR merge metrics
No merged PRs in 30d

Description

Version: LECmd 2026.5.0 (net9)

Summary

For LNK files where the target path exists only in the EnvironmentVariableDataBlock, the JSON and CSV output contain no target path at all. `ExtraBlocksPresent `reports that the block exists, but its contents are not written to either format. The console output shows the value correctly, so this appears to be an output-serialization gap rather than a parsing problem.

Reproduction

A Control Panel shortcut (system-shipped, benign — used here only because it's a clean, easily reproduced example of the structure):

LECmd.exe --json . --pretty -f 907aee15304e.lnk

JSON output:

```
json
{
"SourceFile": "C:\\tools\\EZSuite\\net9\\907aee15304e.lnk",
"SourceModified": "2012-07-25T20:19:48.2602134+00:00",
"WorkingDirectory": "%windir%\\system32",
"HeaderFlags": "HasName, HasWorkingDir, HasArguments, HasIconLocation, IsUnicode, ForceNoLinkInfo, HasExpString, PreferEnvironmentPath",
"Arguments": "shell32.dll,Control_RunDLL",
"ExtraBlocksPresent": "PropertyStoreDataBlock, EnvironmentVariableDataBlock"
}

```
Console output for the same file:

```
>> Environment variable data block
Environment variables: %SystemRoot%\system32\rundll32.exe
```

The value is also visible in a hex view of the file at the expected offset.

Why this matters

The header flags on this file include `ForceNoLinkInfo`, `HasExpString `and `PreferEnvironmentPath`, so there is no LinkInfo structure and consequently no `LocalPath`. The EnvironmentVariableDataBlock is the only place the target is recorded. The JSON therefore reports the arguments (shell32.dll,Control_RunDLL) but not the executable they are passed to.

This shape is not rare, and it is used by malicious LNKs that reach `rundll32.exe`, `mshta.exe` and similar via the environment-variable path. In automated pipelines that consume the CSV or JSON, such a file appears to have no target at all — and there is no way to distinguish "the LNK had no target" from "the target was in a block the output doesn't carry."

The requested change is not conditional on those flags: the block's contents should be written whenever the block is present, since it is also useful when a `LocalPath `exists (the two can differ).

Worth noting the TrackerDataBlock is already promoted to real fields (`MachineID`, `MachineMACAddress`, `TrackerCreatedOn`), so there's precedent in the output format for surfacing block contents

Happy to test a build against LNKs that I have found missing this info

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the LECmd.exe JSON and CSV output paths and reproduce the issue using the provided command and LNK. Trace how EnvironmentVariableDataBlock contents are handled compared with TrackerDataBlock fields, then verify that both formats include the block contents while preserving console output and any existing LocalPath; test against the supplied Control Panel shortcut.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.