Skip to content

Fix review issues from #1375 (quantumstrand correctness/regression fixes) - #1376

Merged
mr-tz merged 21 commits into
mandiant:quantumstrandfrom
vee1e:fix/quantumstrand-review-1375
Aug 19, 2026
Merged

Fix review issues from #1375 (quantumstrand correctness/regression fixes)#1376
mr-tz merged 21 commits into
mandiant:quantumstrandfrom
vee1e:fix/quantumstrand-review-1375

Conversation

@vee1e

@vee1e vee1e commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Addresses the valid issues from #1375

vee1e added 8 commits August 19, 2026 04:39
XOR-obfuscated headers append ' (XOR decoded with key: 0x...)' to the
layout name, so is_structured_layout()'s exact 'pe'/'elf' match failed
and compute_layout() silently fell back to classic static strings,
losing section names, code/reloc/XOR tags, and structure annotations.
Strip any parenthetical suffix before matching.
The help text says -y defaults to not running deobfuscation, but the
prompt branch -y bypasses was the only place stack/tight/decoded got
disabled, so a non-interactive Go/Rust run with -y ran full deobfuscation
anyway (only .NET was force-disabled). -y now skips the prompt and
disables deobfuscation, matching the documented default.
The key was sha256+version only, so interpreting the same bytes under a
different --format (sc32 vs sc64) could serve the other variant's
stack/tight/decoded results. The CLI already disables caching for
non-auto formats, but API callers passing cache_dir were unprotected.
Format is now part of the key, so variants never collide.
PELayout/ELFLayout mark_structures overrides only recursed into children,
never applying structures_by_address to their own strings, so strings in
the ELF header/program-header gap (attached to the root node) and PE
header-gap strings rendered with an empty .structure. Both now annotate
their own strings before recursing, matching MachOLayout.
--summary auto-disables stack/tight/decoded and --analyze-functions
disables static, so the combination silently left every string type
disabled and rendered an empty summary. Since the summary only covers
static strings, which --analyze-functions cannot show, the two are
incompatible and now raise a clear argument error.
The max_len fallback branch tested args.libs twice, so --pes without an
explicit --max-len raised ValueError('unknown extraction type'). The
second condition now checks args.pes.
Only gp.StringHashDatabase checked for a Git LFS pointer; the oss, winapi,
and expert loaders failed with a confusing BadGzipFile/msgspec error on a
fresh clone without git lfs pull. A shared ensure_not_lfs_pointer() helper
now raises the actionable message, and gp's loader is refactored onto it.
Comment thread floss/layout/base.py
Comment thread floss/main.py Outdated
Comment thread tests/test_cli_args.py Outdated
vee1e added 3 commits August 19, 2026 11:51
The CLI flag was already removed; Options.disable_progress remained as a
permanently-False field feeding 5 progress-gating sites. Per review, drop
the flag entirely: quiet now drives those gates directly.
--yes implied it enables deobfuscation, but the flag skips the prompt and
defaults to not running it, which confused reviewers. --no-prompt states
the intent. The dest and Options field become no_prompt (store_true).
Comment thread tests/test_cache.py Outdated
Comment thread floss/pipeline.py Outdated
vee1e added 3 commits August 19, 2026 15:06
compute_key(sha256, version, format='auto') so callers that only need the
default variant don't have to pass it explicitly.
The interactive deobfuscation prompt (and the confusing -y/--yes /
--no-prompt flag that skipped it) is removed entirely. String deobfuscation
is now opt-in: a plain run defaults to static (and language) strings only,
and stack/tight/decoded must be requested explicitly via --string-type.
--analyze-functions requests function-level deobfuscation, so it is not
disabled by the default. This resolves the silent redirect behavior from
mandiant#1176: there is no implicit 'n' anymore, just an explicit default.
Undo the opt-in default from 0abe0c2 (default now runs all string types,
deobfuscation included) per PR mandiant#1376 discussion — the final behavior is
still being debated. The interactive deobfuscation prompt stays removed.
The --summary static-only shortcut and --analyze-functions are unchanged.
Comment thread floss/main.py Outdated
Comment thread floss/pipeline.py
Comment thread scripts/tags/extract_strings.py
Comment thread tests/test_cli_args.py Outdated
Comment thread tests/test_cli_args.py Outdated
vee1e added 6 commits August 19, 2026 17:45
Runs serve cached documents by default, which silently mixes output from
different code revisions. Document FLOSS_CACHE_ENABLE=0 for reproducing
and diffing.
format='auto' is now the default, so tests no longer pass it explicitly.
Previously only non-static values were rejected, silently allowing
--summary --string-type static. --summary is its own static-only view, so
any --string-type/--no-string-type is now an argument error.
MAX_LEN_LIBS (64) now applies to --libs and MAX_LEN_PES (100) to --pes;
they were swapped.
It only re-asserted the Analysis defaults and added a slow full run; the
default all-on behavior is covered implicitly elsewhere.
The layout tree widened \t to 4 spaces while every other view escapes it
to the literal two-char sequence via sanitize(). json.dumps() already
escapes \t (and \n, \r), so dropping the widening makes the layout view
consistent: control chars render as literals and stay on one line.
@mr-tz
mr-tz merged commit 050bfe2 into mandiant:quantumstrand Aug 19, 2026
18 checks passed
@vee1e
vee1e deleted the fix/quantumstrand-review-1375 branch August 19, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants