Reviewed the full diff of #1372 (quantumstrand → master, closes #943). CI is green across the board, but a source-level review turned up 10 issues, several of which silently produce wrong output or regress existing behavior. Filing these to track fixes before merge; plan is to address all of them and rebase the branch on top of master afterward.
High priority — silently wrong output / behavior contradicts docs
Medium priority — regressions / silent misbehavior
Lower priority
Also noted, not blocking
--only/--no were renamed to --string-type/--no-string-type with no backward-compat alias, and floss/version.py is still 3.1.1 despite this being a major feature release — worth a version bump alongside the fixes above.
Plan
Address all ten items above, then rebase quantumstrand onto current master before merging.
Reviewed the full diff of #1372 (
quantumstrand→master, closes #943). CI is green across the board, but a source-level review turned up 10 issues, several of which silently produce wrong output or regress existing behavior. Filing these to track fixes before merge; plan is to address all of them and rebase the branch on top ofmasterafterward.High priority — silently wrong output / behavior contradicts docs
XOR-decoded PE/ELF layouts fail the structured-layout check (
floss/enrich.py:34)is_structured_layout()does an exact match on"pe"/"elf", but an XOR-obfuscated header gets" (XOR decoded with key: 0x...)"appended tolayout.name(floss/layout/pe.py:342,floss/layout/elf.py:260). The check then fails andcompute_layout()silently falls back to classic static strings — losing section names, code/reloc/XOR tags, and structure annotations for exactly the obfuscated-malware case FLOSS is built to handle.-y/--yesdoesn't skip deobfuscation for Go/Rust binaries (floss/pipeline.py:396)The flag's help text says deobfuscation "defaults to not running it," but that only happens inside the interactive-prompt branch, which
-ybypasses entirely. Only.NETgetsenable_stack/tight/decoded_stringsforce-disabled elsewhere (floss/pipeline.py:387-389); Go/Rust binaries keep theAnalysis()default ofTrue. A non-interactive/CI run with-yon a Go or Rust sample runs full deobfuscation anyway.Static-strings path now reads the whole file into memory, bypassing the large-file guard (
floss/pipeline.py:309)sample.read_bytes()runs unconditionally before theMAX_FILE_SIZE/--large-filecheck (floss/pipeline.py:504), which now only guards the deobfuscation stage.master's equivalent path usedmmap(floss/utils.py: get_static_strings) specifically to avoid this. Regression risk: OOM or a large perf hit on big samples even for--string-type static-only runs.Medium priority — regressions / silent misbehavior
--disable-progressCLI flag silently removed (floss/cli.py)Present in
master's parser, dropped from the rewrittenfloss/cli.py.floss/pipeline.py(Options.disable_progress, gated in 5 places) still fully implements it as dead code that's permanentlyFalse. Existing scripts using--disable-progressnow hit anargparse"unrecognized arguments" error, with no replacement short of-q/--quiet(which also silences other output).Cache key ignores
--format, can serve stale/wrong results (floss/cache.py:216)The cache key (
sha256+ version) andcovers()never account forOptions.format. Analyzing the same shellcode bytes first with--format sc32then--format sc64returns the stale sc32-interpreted stack/tight/decoded strings — vivisect never re-runs under the new interpretation.PE/ELF root-level strings never get structure annotations (
floss/layout/base.py:334)PELayout.mark_structures/ELFLayout.mark_structuresoverride the base method but only recurse into children — neither appliesstructures_by_addressto the node's ownself.strings.MachOLayoutdoes this correctly by callingsuper().mark_structures(). Effect: strings in the ELF header/program-header/section-header gap (attached to the root layout node, sinceelf.pydoesn't tile a header child the waype.pydoes) render with an empty.structure, so--structure elf-headernever matches them even though the structure was recorded at that offset.--summary+--analyze-functionssilently disables every string type (floss/main.py:227)--summaryauto-disables stack/tight/decoded when no--string-typeflags are given;--analyze-functionsthen sees an emptyenabled_string_typesand additionally disablesstatic. Result: nothing enabled, no error raised — just an empty/meaningless summary.Viewer tag filter uses AND instead of OR semantics (
viewer/src/App.tsx:556)The tag-filter checkbox list uses
.every()(a string shows only if all its tags are checked) instead of.some(). Unchecking one tag hides every string that carries that tag, even if another of its tags is still checked — inverted from the OR semantics a multi-select checkbox filter (and the per-tag counts shown next to it) implies.Lower priority
Typo makes
--pesmode unreachable inextract_strings.py(scripts/tags/extract_strings.py:265)if args.libs: max_len = MAX_LEN_PES elif args.libs: max_len = MAX_LEN_LIBS— the second condition should beargs.pes. The script's own documented usage (extract_strings.py -d --pes C:\Windows cwinpes) raisesValueError("unknown extraction type")when run without an explicit--max-len.Git-LFS-pointer detection missing from 3 of 4 tag database loaders (
floss/tags/oss.py,winapi.py,expert.py)Only
floss/tags/gp.py:140(StringHashDatabase.from_file) checks for an unpulled LFS pointer and raises"Git LFS pointer detected ...; please run \git lfs pull`". The other loaders don't, so a fresh clone withoutgit lfs pullgets a confusing rawgzip.BadGzipFile: Not a gzipped fileor amsgspec` decode error instead of an actionable message.Also noted, not blocking
--only/--nowere renamed to--string-type/--no-string-typewith no backward-compat alias, andfloss/version.pyis still3.1.1despite this being a major feature release — worth a version bump alongside the fixes above.Plan
Address all ten items above, then rebase
quantumstrandonto currentmasterbefore merging.