Malspark

Concepts

Debate and judge

How the analysts argue over their claims, when the debate ends, and how the judge reaches the verdict.

After the analysis stages, each analyst has filed its claims. They rarely agree on everything: one reads a routine as a mutex check, another as a licence check; one says a host is C2, another says it is a revocation lookup. The debate settles what it can with evidence, and the judge decides the rest.

The debate loop: analysts file claims, the mediator lists contradictions, the named analysts revise, and the loop ends in the judge's verdictAnalystsclaims with ev_ citationsMediatorreads claims and ledgerlists contradictionsAnythingblocking?Named analysts revisewith the disputed entries in frontof them; may call tools againJudgeverdict, family, techniqueschecked, then STIX 2.1yes, and rounds leftnext roundno, or a stop rule applies

The mediator

The mediator runs on the judge's model. In each round it reads every analyst's report and its structured claims. It has tools of its own: it can read any ledger entry and ask an analyst a direct question. It decides what to read; nothing limits its calls.

It ends its answer with a block that lists every contradiction still standing. Each line names the analysts who must answer it and says whether it blocks. Two lines from the first round of the benchmark run:

CONTRADICTIONS:
[analysts: TRIAGE ANALYST, STATIC ANALYST, ALL_TOOLS_QU1CKSC0PE ANALYST] Claim: the 0x6f48 download routine is not linked to any file-write routine, so a fetched body is not shown written to disk (TRIAGE claim 24; STATIC claim 21; QU1CKSC0PE claim 21). Contradicted by ev_0067: the 0x6f48 body calls FUN_1360bc07acc(path, body, length) after its HTML checks, and ev_0068 and ev_0081 show 0x7acc is the file writer. [blocking: the decompiled body in ev_0067 links 0x6f48 to the write routine, so the "not linked" statement is contradicted by the ledger.]
[analysts: TRIAGE ANALYST, STATIC ANALYST, ALL_TOOLS_QU1CKSC0PE ANALYST] Claim: the "LogonTrigger" path (0xc2c4) has no link to a scheduling or COM registration route, and the COM routine 0xc5e8 is not linked to it (TRIAGE claim 23; STATIC claim 22; QU1CKSC0PE claim 23). Contradicted by ev_0092 (0xb344 calls 0xc5e8 and 0xc42c) and ev_0077 (0xc42c calls 0xc2c4, and reaches a RegisterTaskDefinition-style vtable call). [blocking: the call chain is in the ledger, so the stated absence of a link is contradicted.]

A last line, agreement_confidence, gives the mediator's agreement level.

A contradiction can be between two analysts, or between an analyst and a ledger entry. Before it marks a line blocking, the mediator is asked to read the entry the line turns on.

Revision rounds

Only the analysts a blocking line names revise. Each one sees the lines that name it and the stored text of the entries those lines cite. It may call its tools again. Every other analyst keeps its answer.

The code watches each revision but never rewrites it:

  • A value a revision silently drops is recorded, so a claim cannot vanish without trace.
  • A rise in agreement that no new evidence explains is flagged as possible sycophancy. It is reported, not blocked.

When the debate ends

EndWhenConsensus claimed
consensusThe agreement level reaches the threshold (negotiation.consensus_threshold, 0.85 by default) and no line blocks.Yes
convergedEvery revision repeats the answer in force, or the agreement level stops moving with nothing blocking.Yes
rewordedEvery revision states the same claims in other words.No
contested_points_unchangedA round left every contested point as it was.No
carried_without_new_evidenceA point went through two rounds with nothing new to read.No
hard_limitThe round limit was reached (negotiation.max_iterations, 5 by default) with blocking lines left.No
not_applicableFewer than two analysts filed claims, so there was nothing to compare.No
mediation_failedThe mediator's call failed or timed out.No

At the round limit, the mediator gets one more question: for each line still blocking, do the cited entries uphold it? Its ruling is written onto the claims the line names. No analyst is called again.

The run summary records the reason as negotiation.termination_reason, with the agreement level after each round.

The judge

The judge works after the debate, with the same tools. It reads the claims in force, the debate record and the evidence, and states:

  • the verdict: Malware, Suspicious or Benign, with a confidence;
  • the severity and the category;
  • the family, with its own confidence;
  • the ATT&CK techniques it publishes.

The verdict is the judge's own words. The code never derives it from the shape of the STIX bundle or from a score.

Each technique is checked before it is published. The id must exist in the ATT&CK catalogue for the sample's platform, and a claim behind it must describe the behaviour. A technique that fails is sent back to the judge with the reason, and one it cannot support is dropped. The report's ATT&CK section lists what was dropped and why. In the benchmark run, the judge published 22 techniques and dropped two, among them process injection: its card requires code or data written into another live process.

The judge's answer is written as a STIX 2.1 bundle: the malware object, an attack pattern per technique, and indicators for the IOCs it publishes.

Settings

SettingDefaultEffect
negotiation.max_iterations5The round limit. A job can set its own with max_iterations.
negotiation.consensus_threshold0.85The agreement level that counts as consensus when nothing blocks.

A team's debate stage can set how hard it argues; see Agents and teams. The mechanics in full, rule by rule, are in Architecture.

Edit on GitHub

On this page