HexCore Pythia Oracle Analysis · git:20260422.76de8e7 · 2026-04-22 · sha256 32a12805634b3bd8

HexCore Pythia Oracle Analysis git:20260422.76de8e7A

Immutable. This exact content is served forever at /api/v1/blob/32a12805634b3bd8.

---
name: HexCore Pythia Oracle Analysis
description: Skill to drive Claude-powered emulation intervention (Project Pythia / Oracle Hook / Issue #17). Teaches Claude to write Oracle-enabled HexCore jobs, interpret Pythia decisions, and delegate to specialists.
---

# HexCore Pythia Oracle Analysis — v0.1-hackathon

> **Hackathon context (Apr 21-26 2026):** this skill drives **Project Pythia**, a Claude Agent that intervenes in HexCore's emulation mid-execution. Pythia receives a `DecisionRequest` at every configured trigger (timing check, PEB access, software breakpoint, exception), inspects state, and issues a `DecisionResponse` (continue / patch / skip / abort). HexCore applies the decision and resumes. **This is the first Claude-driven dynamic malware analysis pipeline.**

> **Companion skill:** `.agent/skills/hexcore/SKILL.md` covers baseline static + dynamic analysis. Use that one when a sample can be understood without live intervention. Use *this* skill when the sample uses anti-debug / packing / API-hash resolution that blocks normal emulation.

---

## When to Use This Skill

Prefer this skill over the baseline HexCore skill when any of these is true:

1. Baseline `hexcore.debug.emulateFullHeadless` trips anti-debug and exits silently (empty `apiCalls`, no `stdout`, no behavior observed).
2. The sample has high-entropy sections + `rdtsc` / `QueryPerformanceCounter` / `GetTickCount` / PEB dereferences visible in disassembly (classic timing & environment anti-debug).
3. Imports table is suspiciously small for the binary's size — indicates API hash resolution at runtime.
4. You need to observe the beacon / C2 / URL that only surfaces AFTER the anti-debug gauntlet is cleared.
5. The user explicitly mentions Pythia, Oracle, or Issue #17.

If the sample is trivial (unpacked, normal imports, no timing checks), use the baseline HexCore skill — Pythia is overkill and burns API credits.

---

## Architecture (60-second version)

```
HexCore workspace
  ├── {name}.hexcore_job.json          ← you create this
  └── Project-Pythia/ (external clone) ← user provides path via setting

1. You write a job file with an `oracle` block in an emulation step.
2. HexCore pipeline auto-detects the job file and runs each step.
3. When the step reaches an emulation command tagged `oracle: {...}`:
     a. HexCore spawns Pythia (Node subprocess in Project-Pythia/).
     b. Handshake over NDJSON stdio.
     c. Oracle injects 0xCC (INT3) bytes at every trigger PC.
     d. Emulation starts. On INT3 hit, emu pauses, state is captured,
        a DecisionRequest is sent to Pythia, a DecisionResponse is read.
     e. Byte is restored, RIP rewound, patches applied, emulation resumes.
4. Output files land in outDir: oracle-session.log + oracle-decisions.json.
5. You read those files and report findings.
```

**Transport:** stdio NDJSON — the ONLY option. Pythia is a separate Node subprocess, so SharedArrayBuffer isn't applicable (SAB doesn't cross process boundaries in Node). Do NOT confuse this with Project Perseus SAB, which operates INSIDE the main process between C++ and JS for Unicorn hook callbacks — that stays on its own path, untouched by Oracle. The stdio overhead is ~10µs per frame; a Claude decision takes 5-25s, so transport latency is irrelevant.
**Models:** Haiku 4.5 default, Sonnet 4.6 on crypto/unpacking/exception, Opus 4.7 reserved for one `identify_family` call per session. Routing is automatic inside Pythia.
**Budget:** per-session hard cap in `hexcore.oracle.maxBudgetUsd` (default $5). Pythia degrades to deterministic stubs above budget.

---

## Settings the User Must Configure

These must be set in VS Code settings.json before any Oracle step runs:

| Setting | Required | What |
|---|---|---|
| `hexcore.oracle.enabled` | **YES** | Must be `true`. Default `false` guards v3.8.0 behavior bit-identical. |
| `hexcore.oracle.pythiaRepoPath` | **YES** | Absolute path to the Project-Pythia clone. Typical: `C:\\Users\\Mazum\\Desktop\\HexCore-Oracle-Agent`. |
| `hexcore.oracle.maxBudgetUsd` | no | Session hard cap. Default `5.0`. Lower for CI, higher for deep analysis. |
| `hexcore.oracle.pauseTimeoutMs` | no | Max wait per decision before fallback. Default `30000`. |

There is NO transport selector — stdio is hard-wired. Earlier drafts of this
skill mentioned `hexcore.oracle.defaultTransport` with an `sab` option; that
setting was removed in Phase 4 because SharedArrayBuffer doesn't cross Node
process boundaries and the whole point of stdio is the process isolation.

Pythia also needs `ANTHROPIC_API_KEY` set — it reads from `$PYTHIA_REPO/.env` automatically (gitignored).

---

## Job File Format — Oracle Steps

Oracle is layered ON TOP of the existing `hexcore.debug.emulateFullHeadless` command. You do NOT write a new step kind — you add an `oracle` field to the args of an existing emulation step.

### Minimal Oracle job

```json
{
  "file": "C:\\samples\\malware-v5.exe",
  "outDir": "C:\\reports\\malware-v5-oracle",
  "quiet": true,
  "steps": [
    { "cmd": "hexcore.filetype.detect" },
    { "cmd": "hexcore.peanalyzer.analyze" },
    { "cmd": "hexcore.disasm.analyzeAll" },
    {
      "cmd": "hexcore.debug.emulateFullHeadless",
      "timeoutMs": 300000,
      "args": {
        "arch": "x64",
        "permissiveMemoryMapping": true,
        "maxInstructions": 5000000,
        "oracle": {
          "triggers": [
            { "kind": "instruction", "value": "0x140001a3f", "reason": "QPC timing check at sv_t1" },
            { "kind": "instruction", "value": "0x140001b80", "reason": "PEB BeingDebugged read at sv_t3" },
            { "kind": "exception",   "value": "*",            "reason": "unmapped read fallback" }
          ]
        },
        "output": { "path": "emulation.json", "format": "json" }
      }
    },
    { "cmd": "hexcore.ioc.extract" },
    { "cmd": "hexcore.pipeline.composeReport" }
  ]
}
```

### `oracle` arg schema

```typescript
{
  // Required. Each trigger registers a pause point with Pythia.
  triggers: Array<{
    kind: "instruction" | "api" | "exception" | "timing_check" | "peb_access";
    value: string;   // "0x..." for instruction; API name for api; "*" for exception fallback
    reason: string;  // human-readable — appears in Pythia's context + logs
  }>;

  // Optional — override the default Pythia budget for this one step.
  maxBudgetUsd?: number;

  // Optional — dry-run: write DecisionRequests to outDir but accept automatic
  // "continue" on all of them. Useful for measuring trigger firing rates
  // before spending real credits.
  rehearseOnly?: boolean;
}
```

### Output files (alongside existing emulation output)

Oracle steps write TWO additional files into `outDir`:

- `oracle-session.log` — line-by-line trace of every pause: timestamp, eventId, trigger, action, reasoning, cost. Human-readable.
- `oracle-decisions.json` — structured array of `{ eventId, trigger, request, response, model, costUsd, elapsedMs }`. Machine-readable. Feed this to subsequent analysis steps or to the report composer.

---

## Finding Trigger PCs

You need concrete addresses to register `instruction` triggers. Three ways:

1. **Pre-scan with hexcore pipeline + static analysis.** Chain two steps: `hexcore.disasm.analyzeAll` → a custom filter step (not yet exposed as a headless command in v3.8.0 — for now, use a pre-analysis subagent, see below). Output: list of PCs matching `rdtsc`, `cpuid`, `mov reg, gs:[0x60]`, `QueryPerformanceCounter` IAT call sites.

2. **Delegate to `analysis-specialist` subagent** (for complex samples, recommended). Send the agent a clear brief: *"Use hexcore-strings + hexcore-disasm + hexcore-peanalyzer pipeline steps to identify anti-debug trigger PCs in `{sample}`. Return a list of `{pc, pattern, reason}`. Do not run emulation."* The agent produces a list you paste into the `oracle.triggers` array.

3. **Use documented PCs from prior runs.** If this sample is `Malware HexCore Defeat v5` or `v6.1`, the known trigger PCs are cached in `docs/pythia-oracle-templates/known-samples.md` (TODO by user).

---

## Typical Workflows

### Workflow A — "Analyze this unknown sample with Oracle" (the demo flow)

```
1. Verify user's oracle config is sane (read settings).
2. IF sample is unknown → delegate pre-scan to analysis-specialist to
   identify anti-debug trigger PCs.
3. Write {sample-name}-oracle.hexcore_job.json with:
     - filetype.detect + peanalyzer.analyze (static prep)
     - disasm.analyzeAll (so Helix can decompile later)
     - debug.emulateFullHeadless with oracle.triggers from step 2
     - ioc.extract + pipeline.composeReport (gather findings)
4. Drop the job into the HexCore workspace — pipeline auto-detects.
5. Monitor the job's outDir for oracle-session.log. Parse pauses as
   they appear.
6. When status.json shows all steps completed:
     - Read oracle-decisions.json to see what Pythia did at each pause.
     - Read the composed report for IOCs, beacon URLs, extracted strings.
7. Summarize for the user: how many pauses, total API cost,
   beacon URL (if observed), comparison vs baseline emulation.
```

### Workflow B — "Compare baseline vs Oracle emulation"

Ideal for the hackathon demo video. Run the SAME sample twice:

```
1. Run {sample}-baseline.hexcore_job.json WITHOUT oracle.
2. Observe: no beacon, apiCalls stop early, behavior looks benign.
3. Run {sample}-oracle.hexcore_job.json WITH oracle.
4. Observe: Pythia bypasses anti-debug, beacon surfaces, real behavior
   visible.
5. Compose side-by-side report diffing the two runs.
```

### Workflow C — "Rehearsal mode" (zero API cost)

For iterating on trigger PCs without burning credits:

```
1. Write the job with oracle.rehearseOnly: true.
2. Run — each pause gets an automatic "continue" decision, logged as
   rehearsal in oracle-session.log.
3. Inspect how many pauses fired and at which PCs. Adjust triggers.
4. When satisfied, flip rehearseOnly → false. Budget charge begins.
```

---

## Interpreting Oracle Decisions

Every line in `oracle-session.log` follows this shape:

```
[2026-04-22T14:31:02.143Z] pause#3 trigger=instruction:0x140001b80 (PEB BeingDebugged read)
  → action=patch model=haiku cost=$0.0087 elapsed=6.2s
  → reasoning: "PEB+0x2 byte is 0x01 (debugger present) — patched [rax+0x2]=0 to bypass IsDebuggerPresent"
  → patches: [{target:memory,location:0x7FFE0002,value:0x00,size:1}]
```

**Key fields:**

- **action** — the verdict: `continue`, `patch`, `skip`, `patch_and_skip`, `abort`.
- **model** — which tier Pythia used. `haiku` = mechanical (timing / PEB flip / NQIP class 7). `sonnet` = crypto / unpacking / multiple indirect calls. `opus` = family identification, once per session max.
- **cost** — actual USD burned. Sum these + compare against the session budget.
- **reasoning** — one line. If reasoning is empty or starts with `[fallback]`, that pause got a timeout/error fallback — investigate.

**When to worry:**

- More than 5 `[fallback]` reasonings in a run → transport unhealthy or Pythia timing out. Raise `pauseTimeoutMs`.
- `modelUsed=opus` firing more than once → escalation logic got stuck. Inspect the last few decisions.
- Total cost > budget × 0.8 → pipeline degrading to rehearsal soon. Stop or bump budget.

---

## Delegating to Specialists

Oracle analysis pairs well with subagent delegation when the work is large:

- **`analysis-specialist`** — pre-scan sample to find trigger PCs; parse YARA / IOC output; extract stringy C2 candidates from `oracle-decisions.json`.
- **`disasm-specialist`** — resolve API hash targets: given an `oracle-decisions.json` entry where Pythia asked about a hash, compute the matching WinAPI name.
- **`emulation-engineer`** — debug Unicorn crashes, check memory mapping when an exception trigger fires unexpectedly.
- **`decompiler-specialist`** — run Helix on the specific function Pythia paused in; feed the pseudo-C back into a follow-up Oracle session for semantic context.

**Pattern:** when the user asks a complex question ("why did v6.1 still evade Pythia?"), kick off a parallel delegation — let the specialist dig while you summarize what the current Oracle decisions already tell you.

---

## Current Limitations (v0.1-hackathon)

1. **Emulator wiring is scaffold-only** as of Apr 21 2026. The `oracle` block on `emulateFullHeadless` lands in commit Phase 3.5 (target Apr 22). Until then:
   - `hexcore.oracle.demoHeadless` works as a **handshake probe** — validates Pythia spawns and transport is healthy.
   - Real INT3-driven emulation is NOT yet interceptable.
   - Use rehearsal fixtures in `Project-Pythia/test/fixtures/` for offline iteration.
2. **Tool round-trip** supports `read_memory` and `get_imports` fully; `disassemble`, `query_helix`, `search_hql`, `list_strings_near` return stubs in v0.1.
3. **Trigger kinds supported today:** `instruction`, `api` (if resolved to a PC), `exception`. Heuristic triggers (`timing_check`, `peb_access`, `memory_read/write`) route through `instruction` — caller must provide the exact PC.
4. **Self-modifying code** will break INT3 injection — if the sample rewrites the 0xCC byte, the trigger is lost. For v5/v6.1 this is not an issue.
5. **Single session per workspace.** Multi-agent sessions land post-hackathon.

---

## Command / File Reference

| Command | Kind | Purpose |
|---|---|---|
| `hexcore.oracle.demoHeadless` | VS Code command | Handshake probe — spawns Pythia, does handshake, closes. No emulation. |
| `hexcore.oracle.listSessions` | VS Code command | Enumerate active sessions (always ≤ 1 in v0.1). |
| `hexcore.oracle.inspectConfig` | VS Code command | Dump resolved `hexcore.oracle.*` settings to Output Channel. |
| `hexcore.debug.emulateFullHeadless` | Pipeline step | Standard emulation — adds `oracle: {...}` arg to enable intervention (Phase 3.5). |
| `hexcore.pipeline.runJob` | Pipeline | Runs the canonical `.hexcore_job.json` — includes Oracle steps. |

**Example templates:** `docs/pythia-oracle-templates/*.hexcore_job.json` (created by this skill's author).

---

## Troubleshooting

| Symptom | Likely Cause | Fix |
|---|---|---|
| `[oracle-demo] handshake FAILED: handshake timeout` | `pythiaRepoPath` wrong, or Pythia's deps not installed | `cd $PYTHIA_REPO && npm install`; verify path setting |
| Pythia subprocess exits code=1 immediately | Missing `ANTHROPIC_API_KEY` | Create `$PYTHIA_REPO/.env` with the key |
| `pause timeout — falling through to continue` on every pause | Network latency to Anthropic too high, OR Pythia loop stuck | Bump `pauseTimeoutMs`; check Pythia logs in the Output Channel |
| `INT3 at 0xXXXX unmatched — stopping to avoid corruption` | Sample has a native INT3 at that address we didn't inject | Remove that trigger OR investigate whether the sample is probing for self-modifying code |
| Budget exceeded at 80% → forced to Haiku | Normal — routing is cost-aware | Raise `maxBudgetUsd` or let run degrade |

---

*Project Pythia — Oracle Hook for HexCore. Anthropic Claude Developer Hackathon Apr 21-26 2026. Agent SDK + Claude Haiku/Sonnet/Opus + HexCore v3.8.0 + Project Perseus (IPC). Issue #17 implementation — branch `feature/oracle-hook-hackathon`.*