← Back to writing

RESEARCH ESSAY / X86-64 / OWL0

Below the kernel.
Beyond the illusion.

From Blue Pill to virtual machine introspection: what twenty years of research can teach us about control, observation, and the assumptions beneath an operating system.

FIG. 01 / TWO AXES OF AUTHORITY
EXECUTION DOMAIN ↓
CPL 3 · APPLICATION
CPL 0 · KERNEL
VMX NON-ROOT
Guest applicationUser-space rules still apply.
Guest kernelRing 0, inside a guest.
VMX ROOT
Architecture permits CPLsRoot is not a synonym for CPL 0.
VMM / observerA conventional monitor placement.
VMX mode and current privilege level answer different questions. “Ring −1” is shorthand, not an architectural privilege level. This is a conceptual Intel VMX diagram; AMD SVM uses its own host/guest machinery. [7]

01 / CHANGE THE VANTAGE POINT

The kernel is an authority.
It is also an object of study.

Most operating-system observations arrive already interpreted. A process list is the output of a traversal. A file event is the output of a particular instrumentation path. An access decision describes a check that executed. Before treating any of these as evidence, I want to know which state was sampled, which path produced the answer, and which component was allowed to alter either.

OWL0’s motivating question is what becomes possible when that investigation moves below the operating system. The attraction is not the phrase “more privileged.” It is the possibility of choosing a different observation boundary: execution transitions instead of API reports; address translations instead of pointer-shaped guesses; machine events before assigning them a software meaning.

That position creates obligations. The observer must preserve enough machine semantics for its observations to remain meaningful. It must explain its blind spots. It must distinguish a control capability from a reliable interpretation of the state it controls. An observer that can read every byte and explain none of it is powerful in the least useful sense.

THE RESEARCH QUESTION

What must remain true for a below-kernel observation to count as evidence?

This essay uses six reference points, not a claim of direct implementation ancestry. SubVirt and Blue Pill ask what happens when control moves beneath an OS. Ether and DRAKVUF explore external observation. HyperPlatform exposes the engineering surface. The transparency critique supplies the necessary skepticism. The connections to OWL0 are my design interpretations.

02 / READ THE MECHANISMS, NOT JUST THE NAMES

Six reference points.

SubVirt: move the authority boundary.

King and colleagues’ SubVirt paper studies a virtual-machine-based rootkit that loads beneath an existing operating system. Its prototypes use VMware and Virtual PC, with a host OS supporting the VMM. The target OS boots as a guest; services outside that guest can examine its state. Installation assumes substantial existing privilege and changes the boot path. This is not a demonstration that an unprivileged instruction magically acquires control of the machine. [1]

The architectural distinction is between hiding an object inside the target’s bookkeeping and moving it outside the target’s authority. The paper also names the semantic gap: disk blocks, memory and packets are not automatically files, variables and connections. External placement changes access to state; interpreting that state remains separate work.

What I take from it: draw the authority boundary before designing an event format. For each observation, identify the producer, translator and consumer. A trustworthy transport cannot repair an untrustworthy interpretation.

Blue Pill: continuity across a change of execution domain.

Rutkowska’s 2006 Blue Pill presentation turns to AMD SVM and the possibility of moving a running OS into guest execution. The simplified model prepares a VMCB and enters the guest with VMRUN; execution continues under the new virtualization boundary. That continuity is the interesting technical idea. The original work should not be retold as an Intel VMCS implementation, nor should later EPT techniques be projected backward into it. [2]

A VMCB carries control and guest-state information, but AMD’s machinery is not an Intel field layout with different names. Intercepts, state management and exit reporting require vendor-specific reasoning. “Hardware virtualization” identifies a family of capabilities, not one interchangeable programming interface.

What I take from it: treat an execution-domain transition as a continuity problem. Which architectural values survive, which require explicit preservation, and which pending events can become observable at the boundary? The research value lies in accounting for that transition, not in repeating an invisibility slogan.

Compatibility is not transparency: define the observer.

Garfinkel, Adams, Warfield and Franklin challenge the inference that a VMM which runs normal software correctly is indistinguishable from hardware. Their taxonomy includes logical discrepancies, device differences, timing and resource effects. Removing one detector does not establish equivalence against a dedicated observer with a different measurement strategy. [3]

The paper’s argument matters beyond anti-VM checks. “Transparent” is incomplete without an observer, a set of observables and an experiment. Application correctness, absence of an in-guest agent, and undetectable instrumentation are different properties. A result about one does not prove the other two.

What I take from it: turn adjectives into testable contracts. Replace “transparent observation” with a statement of which architectural outputs must be preserved, which timing effects are measured, and which effects remain outside the claim. A limited result with a precise boundary is more useful than an absolute result with an undefined observer.

Ether: an observation mechanism has its own fault semantics.

Ether uses Intel hardware virtualization and Xen to analyze execution outside the target OS. Its memory-write monitoring uses shadow page tables: remove write permission, intercept the resulting fault, allow the relevant operation, then restore monitoring. Normal guest faults must remain distinguishable from faults introduced by analysis. Its instruction-level monitoring also deals with the trap flag and debug exceptions. [4]

Two historical details matter. This is not a description of an EPT-based monitor. And Ether’s discussion distinguishes hiding the analyzer from hiding virtualization itself. Its syscall tracing includes the Windows SYSENTER path; that mechanism cannot simply be relabeled as a modern Linux x86-64 SYSCALL design.

What I take from it: record why an event occurred before interpreting what it means. A fault caused by instrumentation is not evidence that the guest attempted an architecturally invalid operation. An observation pipeline should retain this provenance instead of flattening both into “memory fault.”

DRAKVUF: outside the guest, inside the semantics.

Lengyel and colleagues’ 2014 DRAKVUF work combines Xen and hardware virtualization with analysis of internal kernel behavior. Its contributions include monitoring kernel functions and following filesystem activity through kernel heap allocations. This shifts analysis beyond a narrow set of user-level interfaces. [5]

The project’s documented stack uses Intel VT-x and EPT and supports agentless observation; its later documentation also describes multi-vCPU support and symbol/profile preparation. Those are properties of the evolving project, not a reason to assign every current mechanism to the 2014 paper. [6]

What I take from it: selecting a useful observation point requires software knowledge. A low-level event acquires meaning through a particular ABI, layout and lifecycle. I want that interpretation to carry its dependencies with it: the kernel build, the decoding profile, the address-space identity and the confidence of the reconstruction.

HyperPlatform: the small monitor still has large obligations.

HyperPlatform is a Windows Intel VT-x research platform centered on selective VM-exit handling, with EPT support. Its separation between initialization, exit handling and higher-level experiments makes it useful as a code-reading reference. Its repository is now archived; it is a historical engineering reference, not an implied recommendation for a supported deployment. [8]

The user documentation makes the practical constraints explicit: avoid arbitrary OS API use in an exit handler, prepare resources in a suitable context, and do not confuse a host address-space mapping with the guest mapping of the same linear address. These are not cosmetic driver concerns. They determine whether an observer can survive the situation it is attempting to inspect. [9]

What I take from it: keep mechanism and interpretation separable. The component responsible for restoring a valid machine state should not also need to perform complex symbol lookup, format prose, or wait for storage.

ReferenceQuestion it sharpensConstraint to retain
SubVirtWho controls the platform?Placement and interpretation differ.
Blue PillCan execution continue across a new boundary?State continuity is an obligation.
Transparency critiqueWhat can an observer distinguish?State the observation model.
EtherWhich events did analysis itself introduce?Preserve fault provenance.
DRAKVUFWhat does this machine event mean?Bind decoding to a guest profile.
HyperPlatformCan the monitor handle its own context?Keep the critical path bounded.

03 / THE EXECUTION CONTRACT

A VM-exit is a boundary,
not an explanation.

Intel VMX root/non-root operation is orthogonal to the guest’s CPL. A guest kernel can execute at CPL 0 in non-root operation. A guest user-to-kernel transition is therefore not, by itself, a transition to the VMM. Whether an operation produces an exit depends on its architectural behavior and the configured controls. “Every syscall traps to the hypervisor” is an unsafe premise for an observation design. [7]

In Intel’s model, the VMCS separates guest state, host state, execution controls, entry/exit controls and exit information. VM-entry and VM-exit perform specified state transfers; they do not serialize every conceivable processor state into an all-purpose snapshot. HyperPlatform’s exit path, for example, explicitly carries general-purpose registers in its software context. Register preservation, extension-state policy and the compiler’s assumptions must agree. [10]

FIG. 02 / ONE INTERCEPTED INSTRUCTION

A conceptual Intel VMX flow. Step through an intercepted CPUID; this is a teaching model, not a CPU emulator.

  1. 01Guest runsVMX non-root
  2. 02Exit capturedReason + guest context
  3. 03Handler runsObserve / emulate
  4. 04Resume guestValid continuation

1 / 4 — The guest executes in VMX non-root operation. Its CPL does not identify the virtualization domain.

For an emulated CPUID, completing the instruction includes its register results and a correct continuation. A fault or retry case needs different RIP treatment; “always advance RIP” is not a general exit policy.

Classify before consuming.

An event record should distinguish an intercepted instruction, a guest exception, a second-level translation failure and an asynchronous event. Exit reason, qualification, guest RIP and any valid address information belong together. A field being present in a software structure does not make it architecturally valid for every exit. The decoder needs a validity mask, not a convention that zero means “unknown.” [10]

My preferred abstract contract is a transition over an explicitly captured state, with three separate products: evidence, a continuation decision, and deferred interpretation. A handler should not silently let its logging logic determine the continuation.

// Conceptual event schema; not an OWL0 implementation or hardware ABI.
Observation {
    vcpu_id, local_sequence, capture_epoch;
    reason, qualification, valid_fields;
    guest_rip, guest_cr3, translation_root;
    address_if_valid, access_kind_if_valid;
    provenance;       // architectural, instrumentation, unresolved
    decode_profile;   // build identity + schema revision
    loss_counter;     // absence of records is not absence of activity
}

Decision = resume_after_emulation
         | retry_same_instruction
         | deliver_guest_event
         | stop_with_diagnostic;

Pending events are part of the state.

A correct continuation must account for interruption state, not just registers. If an exception or interrupt was being delivered when control changed, losing that information can suppress an event; reinjecting it twice can manufacture one. Interrupt blocking and event-delivery rules constrain when a guest event can be injected. This is why a generic “handle exit, add instruction length, resume” loop is an inadequate model. [7]

For OWL0’s research direction, I would make every supported event class answer three review questions: What evidence did the processor actually provide? What state does our intervention change? Why is this continuation equivalent to the intended guest behavior? If the third answer is merely “it did not crash,” the experiment has not established its contract.

04 / A POINTER IS NOT A LOCATION

Three addresses.
Two translation authorities.

With guest paging and second-level translation enabled, distinguish guest virtual address (GVA), guest physical address (GPA) and host physical address (HPA). Guest paging describes GVA → GPA; EPT supplies GPA → HPA on Intel. AMD nested paging serves the second-stage role with vendor-specific details. KVM’s MMU documentation distinguishes these translations from shadow paging, which can maintain a direct mapping for execution. [11]

FIG. 03 / TRANSLATION IS COMPOSITION
GVAguest pointer
Guest page tablesguest CR3 + paging mode
GPAguest frame
EPT / NPTsecond-stage root
HPAmachine frame
A logical decomposition. Accesses to the guest’s page-table pages also require second-stage translation; this is not two independent single memory reads. [11]

Decompose the address before telling a story about it.

For a four-level, 48-bit canonical linear-address model with 4 KiB leaf pages, the useful split is 9 + 9 + 9 + 9 + 12 bits. The upper bits must sign-extend bit 47. Five-level paging changes the canonical-width and indexing model; a decoder must know the active mode rather than infer it from the operating system’s branding. Linux documents separate layouts for four- and five-level paging. [12]

FIG. 04 / 48-BIT ADDRESS DECODER

Inspect a canonical virtual address. Indices only: no page tables are supplied, so no GPA or HPA is inferred.

FOUR LEVELS · 4 KiB LEAF · LA57 OFF

PML4 · 47:39273
PDPT · 38:300
PD · 29:21145
PT · 20:12325
OFFSET · 11:00x678

0xffff888012345678 is canonical under the 48-bit model. The offset is 0x678; these indices do not prove that a mapping exists.

A 2 MiB or 1 GiB leaf terminates the walk earlier and uses a larger offset. The bit fields above are deliberately a 4 KiB example.

Consider an observer receiving 0xffff888012345678. The string alone omits an address-space root, paging mode, sampling time and page size. It also omits whether the intended access is instruction fetch, read or write. A useful observation is therefore closer to (address, context, access, epoch) than to a single integer.

A guest PTE can change while the observer walks the hierarchy. A mapping can disappear after it is decoded. Another vCPU can update the object whose pointer has just been read. Correct individual loads do not establish a coherent multi-field snapshot. This suggests an explicit experiment choice: pause relevant execution, use a validated retry protocol, or label the evidence as a potentially inconsistent live read. KVM’s locking documentation illustrates that MMU and memory-lifetime synchronization are explicit subsystems, not incidental details. [13]

A guest page fault and an EPT violation are different events.

A guest paging failure and a second-stage access failure occur under different authorities. The former may need to be reflected as a guest #PF; the latter concerns the monitor’s mapping or permissions. EPT misconfiguration is yet another category. Treating every translation-related exit as a guest page fault corrupts the meaning of the evidence. HyperPlatform’s EPT code separates EPT violation handling from misconfiguration and explicitly manages translation invalidation. [14]

FIG. 05 / THE SAME WRITE, DIFFERENT OWNER

A simplified write-access model: paging structures are readable, entries are otherwise well-formed, and guest protection checks have already been reduced to “allow” or “deny.” EPT #VE delivery is excluded.

Guest protectionALLOW
EPT protectionDENY
EPT violationMonitor policy boundary

Guest protection allows the write, but EPT denies it: an EPT-violation VM-exit in this model. The write has not completed.

In a real walk, second-stage failures can also occur while reading guest page tables. This diagram fixes those accesses as successful so the two final-access authorities can be compared.

There is a second trap here: changing a page-table entry does not by itself establish that every relevant processor will immediately use the new translation. Translation caches, invalidation scope and synchronization belong to the operation. An instrumentation change should have an identifiable activation epoch and a defined set of participating vCPUs. Otherwise a missing event may reflect an old translation rather than an idle guest. [14]

The OWL0 lesson is to make address provenance a first-class part of the notebook. I want a reader to be able to reconstruct which mapping was believed to exist when the observation was captured, and to see when that belief cannot be justified.

05 / READING BYTES IS THE EASY PART

The semantic gap
is a versioned dependency.

An exit caused by executing at a guest address does not contain a field named “process allocated a file object.” Reaching that statement requires decoding: identify an address space, resolve code, interpret the calling convention, reconstruct arguments, follow pointers and establish object lifetime. Each step adds assumptions.

DRAKVUF’s project documentation requires guest-specific symbol information and profiles. The practical implication is that an analysis cannot be specified solely by the monitor binary. The guest build and the interpretation data are part of the analysis configuration. A profile that parses bytes successfully can still describe the wrong layout. [6]

For Linux research, I would separate an address-space identity from a task identity. Threads can share an address space; kernel execution can operate on behalf of different tasks. A control-register value is valuable context, but it is not, on its own, a durable semantic identifier. Likewise, a pointer that referred to one allocation can later refer to another. A memory address is not an object generation number.

// Proposed evidence layers, not a format implemented by the cited projects.
raw:
  vcpu, sequence, reason, rip, cr3, address, validity
context:
  paging_mode, translation_epoch, capture_policy, dropped_records
interpretation:
  guest_build, symbol_profile, decoder_revision, object_generation
claim:
  "candidate write to object X" + evidence_ids + confidence

Never discard raw evidence just because interpretation succeeded.

Two independent questions: was it seen, and was it understood?

A monitor can capture an event perfectly and decode it incorrectly. It can also have an accurate decoder and miss the relevant event. These need separate validation. I would keep a controlled guest workload with independently known behavior, then compare its expected transitions against the raw trace and against the interpreted trace separately.

For a lifetime investigation, a useful synthetic experiment includes allocation, alias creation, release, reuse and a deliberately sequenced late access. The trace must distinguish an address being accessed from the identity of the allocation occupying that address. A mismatch should be reported as an inference failure before it is promoted into a vulnerability narrative.

Multi-vCPU ordering deserves the same discipline. A per-vCPU sequence number gives local order. A host timestamp is not a universal proof of causal order. Where the argument depends on “A happened before B,” the evidence should include the synchronization relationship that supports that statement. A beautiful merged timeline is not a substitute for that relationship.

OWL0 direction: let uncertainty survive serialization. “Unknown mapping,” “profile mismatch,” “capture raced with mutation” and “records dropped” are legitimate results. Converting them into plausible-looking defaults would make the output easier to consume and harder to trust.

06 / THE OBSERVER IS PART OF THE EXPERIMENT

Measure the disturbance.

A monitor consumes execution time, touches memory and introduces scheduling decisions. A low overhead figure cannot establish that a particular race was left undisturbed. Nor does an unchanged instruction result establish that timing-sensitive behavior remained unchanged. This is where the transparency critique becomes an experimental design principle rather than a historical disagreement.

The x86 timekeeping documentation describes how virtualization complicates the relationship between execution, interrupts and clocks. TSC readings require attention to ordering and platform properties; a vCPU can lose execution time while external time continues. Offset or scaling mechanisms affect a guest clock view, but they do not prove equivalence across every possible observer. Historical hardware caveats in that document must be checked against the actual CPU, not copied as universal properties of present systems. [15]

Separate the price of interception from the price of interpretation.

A simple budget helps expose the design pressure. Let N be retired guest instructions in a fixed workload; b its baseline average cycles per instruction; r exits per guest instruction; and c an assumed average incremental cost per exit. Ignoring interactions, the normalized time model is:

Tobserved / Tbaseline ≈ 1 + (r × c) / b

This is an accounting model, not a benchmark. Cache effects, queueing, asynchronous consumers, scheduler interactions and changing workload behavior are omitted. Its purpose is to ask whether reducing an event rate or shortening a critical path is likely to matter under an explicitly chosen assumption.

FIG. 06 / EXIT BUDGET · HYPOTHETICAL MODEL

Fixed baseline: 1 cycle per guest instruction. All values are illustrative inputs, not measurements of OWL0 or any cited system.

1.60× modeled total time · 60% additional time

The bar shows each component’s share of modeled total time, not CPU utilization. Zero intercepted events removes only this model’s exit term; it does not prove zero real-world overhead.

The useful response is architectural. Capture bounded raw records near the event, then interpret them elsewhere. Preallocate capacity where the execution context demands it. Define what happens when capacity is exhausted. If dropping data is the policy, report the loss. If stopping the experiment is the policy, preserve a diagnostic that explains why.

HyperPlatform’s documentation warns specifically about the constraints of its VM-exit handler context and recommends preparing resources outside it. That concrete warning motivates a broader design question: how much infrastructure must remain healthy for the observation path to return control correctly? [9]

An evaluation should be a matrix, not one overhead percentage.

DimensionControlled variationEvidence to retain
ExecutionInterception disabled / enabled; decoding disabled / enabledArchitectural outputs, exit classes, failure reasons
Memory4 KiB / huge pages; remapping; allocation reuseTranslation epoch, leaf size, validity and lifetime context
ConcurrencyOne / multiple vCPUs; deliberate shared-state racesLocal sequence, synchronization markers, loss counters
LoadLow / burst event rates; slow consumerBuffer occupancy, dropped records, tail latency
InterpretationMatching / intentionally mismatched guest profileDecoder rejection behavior and false associations

This is a proposed evaluation structure. It deliberately includes negative tests: malformed evidence, unsupported configurations, profile mismatches and incomplete traces. A research tool earns trust partly through the cases in which it refuses to manufacture a confident answer.

07 / WHAT OWL0 TAKES FROM THIS

Less mythology.
More accountable observation.

The most productive inheritance from these projects is a set of questions. SubVirt changes where authority lives. Blue Pill makes continuity across an execution boundary concrete. Ether forces us to account for instrumentation-induced events. DRAKVUF connects machine-level access to software meaning. HyperPlatform exposes the constraints of the implementation context. The transparency critique keeps the language honest.

For OWL0, I want the unit of progress to be a defensible observation. Not “we are below the kernel,” but “under this execution model, with this translation context and this decoder, this event supports this claim.” That is a much harder sentence to write. It is also one a reader can challenge.

01

Preserve the raw layer.

Keep machine evidence available when semantic reconstruction changes. A new decoder should be able to explain why it reached a different conclusion.

02

Make intervention visible.

Distinguish a guest-generated event from an event manufactured by observation. Account for continuation, retries and event delivery.

03

Bind meaning to context.

A pointer needs a translation context. An object needs a lifetime. A decoded field needs a profile. A causal claim needs ordering evidence.

04

Bound the claim.

Specify the hardware assumptions, capture limitations and perturbations. Treat unknown states as evidence about the experiment, not inconvenient gaps to hide.

There is a recurring temptation in low-level research to treat proximity to hardware as proximity to truth. The machine gives us a different vocabulary: registers, translations, exits, permissions, time. We still have to construct the argument that connects those observations to a system-level claim.

That argument is the part I want OWL0 to make inspectable.

PRIMARY SOURCES / READING PATH

Read below the abstraction.

The six historical reference points are separated from architectural and implementation references. Diagrams and interactive models on this page are original explanations; they are not reproduced figures or reported experimental results.

  1. King et al. — SubVirt: Implementing malware with virtual machines. IEEE Symposium on Security and Privacy, 2006. Read §§2–3 for the placement model and semantic gap.
  2. Joanna Rutkowska — Subverting Vista Kernel for Fun and Profit. Black Hat USA, 2006, Part II: Blue Pill. Original AMD SVM context.
  3. Garfinkel et al. — Compatibility is Not Transparency: VMM Detection Myths and Realities. HotOS XI, 2007. Read the observer model and anomaly taxonomy.
  4. Dinaburg et al. — Ether: Malware Analysis via Hardware Virtualization Extensions. ACM CCS, 2008. §§4.3–4.4 cover monitoring and analyzer transparency.
  5. Lengyel et al. — Scalability, Fidelity and Stealth in the DRAKVUF Dynamic Malware Analysis System. ACSAC, 2014. DOI: 10.1145/2664243.2664252.
  6. DRAKVUF — project documentation. Agentless analysis, EPT requirements, guest profiles and later project capabilities. Distinct from the 2014 publication.
  7. Intel 64 and IA-32 Architectures SDM, Volume 3C. VMX operation, VMCS, VM-entry/exit and EPT. Use the relevant processor capabilities and manual revision when implementing.
  8. Satoshi Tanda — HyperPlatform. Intel VT-x research platform for Windows; archived repository, checked October 2026.
  9. HyperPlatform User Document. In particular, handler-context constraints and guest-memory addressing.
  10. HyperPlatform — vmm.cpp. Software guest context, exit dispatch and per-event handlers.
  11. Linux KVM — The x86 KVM shadow MMU. Translation vocabulary, shadow paging and two-dimensional paging.
  12. Linux x86-64 — Memory Management. Four-level and five-level virtual-address layouts.
  13. Linux KVM — Lock Overview. Explicit synchronization and lifetime constraints.
  14. HyperPlatform — ept.cpp. EPT capabilities, construction, violation handling and invalidation.
  15. Linux KVM — Timekeeping Virtualization for X86-Based Architectures. Clock ordering, virtualization and platform-dependent assumptions.

Read historical experiments in their original hardware and OS context. Modern EPT, nested paging, five-level paging and confidential-computing configurations are not interchangeable assumptions. This essay concerns conventional guest-visible state; it does not claim unrestricted introspection into encrypted or otherwise protected guests.

END OF NOTE / OWL0Corrections, counterexamples, better questions? ↗