Lesson 09 / 18
Sandbox Analysis
Measuring sandbox analysis in terms of suppressed behavior: 5 of 14 items noticing the environment on a stock image and not showing their decisive behavior, the number of resolved items rising from 7 to 12 while total time rises from 288 minutes to 965 minutes, one environment hint being impossible to hide in any environment, and analysis leaving zero records on the target while dropping a trace on the other side.
Published Updated
In this lesson
- Measures an item's hiding by the number of environment hints it checks against observed behavior count
- Separately counts items that turn into evidence, come out clean, and stay undetermined across three analysis environments
- Computes prep, observation, and manual-review time together with the trace left on the other side
Contents
The previous three tools worked over the network. A portion of the items that need examining during an assessment, though, come from a file: an unknown executable found on an endpoint, an archive extracted from an attachment, a helper tool the field team obtained from outside. There is no way to learn what these do by sending requests; the only way to learn is to run the item in an isolated place and observe its behavior.
The sandbox’s isolation strength was measured in the Endpoint and System Hardening course and is taken as input here; what is measured in this lesson is not isolation but analysis’s yield. The only question is: how many of an item’s behaviors can be observed, how many of them notice that the environment is an analysis environment and hide, and how many items end up unable to be decided.
Environment Hints and Hiding
An item can look at the environment it is running in while it runs. What it looks at are the traces that separate analysis environments from real endpoints: the machine having been up for a very short time, the low number of devices, an empty user history, traces left by analysis tools, an accelerated clock, uniform network responses. If even one of these traces is still standing, the item recognizes the environment and never shows its decisive behavior — it runs, does a few harmless things, and stops.
Every trace can be hidden, and each one carries a prep cost: refurbishing the image, building a fake user history, cleaning up tool traces. One trace falls outside this. The only way to fix uniform network responses is to let the item reach a real target; in an authorized assessment this step is out of scope, and connecting to another party’s infrastructure without written authorization is both illegal and unprofessional. This trace is a boundary that prep cannot close.
- AT22. The hint catalog, environments, item list, and behaviors are a model; no real item was run. Items are referred to only by the hints they check and the class of behavior observed.
- AT23. Isolation strength is not measured here; it is taken as input.
- AT24. An item that has at least one of the hints it checks not hidden notices the environment and does not show its decisive behaviors. It keeps showing its harmless behaviors.
- AT25. For a behavior to be visible, the observation window has to be larger than its delay. Delays and windows were written by hand; there is no randomness.
- AT26. The decision is three-valued. Evidence: a decisive behavior was observed. Clean: the item was not hidden, all its behaviors fit in the window, and none was decisive. Undetermined: every remaining case.
- AT27. The decisive marker belongs to the behavior, not the item; a legitimate item can also show a behavior counted as decisive.
- AT28. Analysis does not run in the target environment; it does not produce records on target systems.
// alan/observe.mjs — this is a model of SANDBOX ANALYSIS. No real item is run; // items are referred to only by the environment hints they check and the class of behavior // observed. Isolation strength is not measured here; it is taken as input from the Endpoint // and System Hardening course. // hint -> the prep cost of hiding that hint (min) export const HINT = { 'short-uptime': 8, 'low-device-count': 12, 'known-tool-traces': 15, 'empty-user-history': 20, 'accelerated-clock': 10, 'uniform-network-response': 0, }; // Analysis environment: which hints it hides, how many minutes the observation window is. // 'uniform-network-response' is not hidden in any environment: hiding it requires the item // to reach a real target, and that is out of scope in an authorized assessment. export const ENVIRONMENT = { 'stock-image': { hides: ['short-uptime'], window: 5 }, 'refurbished': { hides: ['short-uptime', 'low-device-count', 'known-tool-traces'], window: 20 }, 'near-real': { hides: ['short-uptime', 'low-device-count', 'known-tool-traces', 'empty-user-history', 'accelerated-clock'], window: 60 }, }; export const MANUAL_MIN = 30; // manual review per undetermined item // row: item | actual | hints it checks | behaviors (name:delay, * = decisive) export const ITEM = ` k01 bad short-uptime file-write:0,*persistence:2 k02 bad low-device-count,known-tool-traces process-creation:0,*credential-read:5 k03 bad empty-user-history file-write:0,*external-connection:10 k04 bad accelerated-clock file-write:0,*timed-trigger:45 k05 bad uniform-network-response process-creation:0,*external-connection:3 k06 bad - file-write:0,*persistence:1,external-connection:4 k07 bad short-uptime,uniform-network-response file-write:0,*credential-read:8 k08 clean - file-write:0,process-creation:1 k09 clean - file-write:0,external-connection:2 k10 clean - file-write:0,process-creation:0,external-connection:1 k11 clean - file-write:0,*credential-read:3 k12 clean - file-write:0,timed-trigger:40 k13 clean - process-creation:0,external-connection:35 k14 clean - file-write:0 `.trim().split('\n').map((r) => { const [name, actual, hint, dav] = r.trim().split(/\s+/); return { name, bad: actual === 'bad', controls: hint === '-' ? [] : hint.split(','), behavior: dav.split(',').map((d) => { const [n, g] = d.split(':'); return { name: n.replace('*', ''), decisive: n.startsWith('*'), delay: +g }; }) }; }); // An item that has one of the hints it checks not hidden notices the environment and HIDES: // it never shows its decisive behaviors. export const hides = (k, o) => k.controls.some((i) => !ENVIRONMENT[o].hides.includes(i)); export function observe(k, o) { const p = ENVIRONMENT[o].window; const g = hides(k, o); const observed = k.behavior.filter((d) => d.delay <= p && !(g && d.decisive)); const suppressed = k.behavior.length - observed.length; let decision = 'undetermined'; if (observed.some((d) => d.decisive)) decision = 'evidence'; else if (!g && suppressed === 0) decision = 'clean'; return { hidden: g, observed: observed.length, suppressed, decision, externalContact: observed.some((d) => d.name === 'external-connection') }; } export function measureEnvironment(o) { const s = { prep: 0, hidden: 0, observed: 0, suppressed: 0, evidence: 0, clean: 0, undetermined: 0, falseEvidence: 0, escaped: 0, externalTrace: 0 }; s.prep = ENVIRONMENT[o].hides.reduce((t, i) => t + HINT[i], 0); for (const k of ITEM) { const r = observe(k, o); if (r.hidden) s.hidden += 1; s.observed += r.observed; s.suppressed += r.suppressed; s[r.decision] += 1; if (r.decision === 'evidence' && !k.bad) s.falseEvidence += 1; if (r.decision !== 'evidence' && k.bad) s.escaped += 1; if (r.externalContact) s.externalTrace += 1; } s.observeMin = ITEM.length * ENVIRONMENT[o].window; s.manualMin = s.undetermined * MANUAL_MIN; s.totalMin = s.prep + s.observeMin + s.manualMin; return s; }
Fourteen Items, Three Environments
// alan/measure.mjs — fourteen items are observed in three analysis environments. import { HINT, ENVIRONMENT, ITEM, MANUAL_MIN, hides, observe, measureEnvironment } from './observe.mjs'; const y = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join('').trimEnd()); console.log(`${ITEM.length} items (${ITEM.filter((k) => k.bad).length} bad), ` + `${Object.keys(HINT).length} environment hints, ${Object.keys(ENVIRONMENT).length} analysis environments`); console.log(`hint never hidden in any environment: ` + Object.keys(HINT).filter((i) => !Object.values(ENVIRONMENT).some((o) => o.hides.includes(i))).join(', ')); const A = [-14, 9, 10, 10, 12, 10, 8, 14, 16]; console.log('\n1. result per environment'); y(A, 'environment', 'window', 'hidden', 'observed', 'suppressed', 'evidence', 'clean', 'undetermined', 'false evidence'); for (const o of Object.keys(ENVIRONMENT)) { const s = measureEnvironment(o); y(A, o, ENVIRONMENT[o].window, s.hidden, s.observed, s.suppressed, s.evidence, s.clean, s.undetermined, s.falseEvidence); } const B = [-7, 8, 23, 23, 23]; console.log('\n2. decision per item'); y(B, 'item', 'actual', ...Object.keys(ENVIRONMENT)); for (const k of ITEM) y(B, k.name, k.bad ? 'bad' : 'clean', ...Object.keys(ENVIRONMENT).map((o) => { const r = observe(k, o); return r.hidden ? `${r.decision} (hidden)` : r.decision; })); const C = [-14, 8, 12, 11, 11, 13, 16]; console.log('\n3. cost and trace'); y(C, 'environment', 'prep', 'observe min', 'manual min', 'total min', 'escaped bad', 'external trace'); for (const o of Object.keys(ENVIRONMENT)) { const s = measureEnvironment(o); y(C, o, s.prep, s.observeMin, s.manualMin, s.totalMin, s.escaped, s.externalTrace); } const h = measureEnvironment('stock-image'), g = measureEnvironment('near-real'); console.log(`\nitems resolved ${h.evidence + h.clean} -> ${g.evidence + g.clean} / ${ITEM.length}`); console.log(`items detecting env ${h.hidden} -> ${g.hidden} / ${ITEM.length}`); console.log(`records produced on target 0 (analysis does not run in the target environment)`); console.log(`manual review time ${MANUAL_MIN} min/item`);
14 items (7 bad), 6 environment hints, 3 analysis environments hint never hidden in any environment: uniform-network-response 1. result per environment environment window hidden observed suppressed evidence clean undetermined false evidence stock-image 5 5 22 7 3 4 7 1 refurbished 20 4 23 6 4 4 6 1 near-real 60 2 27 2 6 6 2 1 2. decision per item item actual stock-image refurbished near-real k01 bad evidence evidence evidence k02 bad undetermined (hidden) evidence evidence k03 bad undetermined (hidden) undetermined (hidden) evidence k04 bad undetermined (hidden) undetermined (hidden) evidence k05 bad undetermined (hidden) undetermined (hidden) undetermined (hidden) k06 bad evidence evidence evidence k07 bad undetermined (hidden) undetermined (hidden) undetermined (hidden) k08 clean clean clean clean k09 clean clean clean clean k10 clean clean clean clean k11 clean evidence evidence evidence k12 clean undetermined undetermined clean k13 clean undetermined undetermined clean k14 clean clean clean clean 3. cost and trace environment prep observe min manual min total min escaped bad external trace stock-image 8 70 210 288 5 3 refurbished 35 280 180 495 4 3 near-real 65 840 60 965 2 5 items resolved 7 -> 12 / 14 items detecting env 5 -> 2 / 14 records produced on target 0 (analysis does not run in the target environment) manual review time 30 min/item
The Suppressed Behavior
The hidden column of the first table is this lesson’s measure. On a stock image, five of
fourteen items notice the environment and never show their decisive behavior. As the environment
is refurbished this number drops to 4, then to 2. While observed behavior rises from 22 to 27,
suppressed behavior falls from 7 to 2.
Hiding is a different thing from a short observation window, and the two need to be told apart. If
the window is short, the behavior has not been seen yet; lengthening it fixes that. If the item
is hiding, the behavior will never be seen; lengthening the window changes nothing, the hint has
to be hidden. The second table reads this distinction item by item: k04 has a behavior with a
forty-five-minute delay and checks the clock hint; seeing it requires both the window to reach sixty
minutes and the accelerated clock to be hidden — one without the other is not enough. By contrast,
k12 and k13 check nothing at all; for them, lengthening the window alone is enough, and both
come out clean in the widest environment.
Which prep step unlocks which item is also read from this table, and the gain is not distributed
evenly. Moving from the stock image to the refurbished environment asks for 27 extra minutes of
prep and turns a single item — k02, which checks both device count and tool traces — into
evidence. Moving from refurbished to near-real asks for 30 extra minutes of prep and a window three
times as long; in return, k03 and k04 turn into evidence, and k12 and k13 turn clean. The
second step does four times the work for a prep cost only slightly above the first, but it does so
by pushing the window from 280 minutes to 840 minutes. Prep is cheap, the window is expensive, and
they are two separate line items.
Two items cannot be resolved in any environment: k05 and k07. Both check the uniformity of
network responses, and that hint is not hidden in any environment. Two of the seven bad items stay
undetermined regardless of the analysis environment’s quality. These two items get handed off
to manual review and appear in the report with the line “analysis could not resolve this.”
Evidence, Clean, and False Evidence
The candidate-evidence gap is read here as three values. Fourteen items arrive at analysis as candidates. On the stock image, 3 turn into evidence, 4 come out clean, 7 stay undetermined. In the best environment there are 6 evidence, 6 clean, and 2 undetermined. The number of resolved items goes from 7 to 12.
Items that come out clean are worth as much as evidence. If all of an item’s behaviors were seen
and none was decisive, that item drops out of the queue — this is the only mechanism that shortens
the candidate list. But the condition for a “clean” decision is strict: the item must not be hidden
and none of its behaviors may have been suppressed. If even a single behavior was suppressed,
the decision goes to undetermined, not clean. This strictness is deliberate, because relaxing it
would let k05 and k07 quietly count as clean.
An error in the opposite direction stands in every environment: the false evidence column is 1 in all three. A legitimate item shows a behavior counted as decisive, and analysis flags it as evidence. Raising the prep, lengthening the window, and hiding hints do not change this line, because what is missing is not observation, it is context. The sandbox sees the behavior; it does not see whether that behavior belongs there, what job the item was set up to do. That is why analysis output alone is not a decision — it is input to one.
Cost and the Trace Left on the Other Side
The third table gives the cost, and it rises in one direction only. Prep goes from 8 minutes to 65; observation goes from 70 to 840. Manual review goes the other way — from 210 minutes to 60 — but the drop does not offset the rise: the total goes from 288 minutes to 965 minutes, more than tripling. In return, the number of resolved items rises by five, and the number of escaped bad items falls from 5 to 2. The cost paid per item is roughly 135 minutes.
The last column is a kind of trace seen for the first time in this course. Records produced on target systems are zero; analysis does not run in the target environment, none of its requests reach the target. But the number of items that attempt an external connection during observation rises from 3 to 5, and those attempts go somewhere. Even if the controlled network does not let them reach a real target, the attempt itself and its timing can leak outward in a way that tells the other side something. The closer the analysis environment gets to reality, the more behavior an item shows; and every behavior it shows is also a sign that it is being examined.
This splits the course’s trace column in two: the trace the defense sees, and the trace the other side can see. The two point in opposite directions. The trace the defense sees is a sign that the assessment is running transparently inside the organization, and its excess only creates noise. The trace left on the other side is irreversible: learning that an item is being examined is enough for whoever is using it to change their behavior, and it corrupts every measurement after that. The next lesson measures the second one far more sharply.
Summary
- Of fourteen items, five notice the environment on a stock image and never show their decisive behavior; as the environment is refurbished this number falls to 2, and observed behavior rises from 22 to 27.
- Hiding and a short window are separate problems: the first is solved by hiding a hint, the second by lengthening the window, and some items need both at once.
- One environment hint cannot be hidden in any environment, because hiding it requires the item to reach a real target, which is out of scope; two of the seven bad items stay undetermined in every environment for this reason.
- The number of resolved items goes from 7 to 12; items that come out clean are the only mechanism that shortens the candidate list, and its condition is strict.
- False evidence is 1 in all three environments; what is missing is not observation, it is context, and prep does not close that gap.
- Total time goes from 288 minutes to 965 minutes; records produced on target are zero, but the number of items attempting an external connection rises from 3 to 5, leaving a trace on the other side.
Next Step
This lesson measured a single analysis environment’s decision, and two items stayed unresolved. There is a second way to resolve an item: ask the same item to a large number of independent engines and combine the results that come back. This route brings analysis time down from minutes to seconds, and in return raises a new question — how to combine results that contradict each other.
The next lesson takes up multi-engine reputation services on this axis. The same set of items is run through a large number of engines, the false-positive and false-negative rate of the majority decision is measured threshold by threshold, and the cost of trusting a single engine is counted. Alongside this, a privacy cost is computed: sending a file to an outside service is publishing it, and a portion of the items in the fictional measurement network carry subscriber data.
To keep your progress and take notes, Log in
My notes
Log in to take notes.