Skip to main content

Crate visualbasic

Crate visualbasic 

Source
Expand description

Parse and inspect Visual Basic 6 compiled binaries.

This crate provides typed access to all internal structures within a VB6 compiled executable, from the PE entry point down to individual P-Code bytecode instructions.

§Quick Start

use visualbasic::VbProject;

let file_bytes = std::fs::read("sample.exe")?;
let project = VbProject::from_bytes(&file_bytes)?;

println!("Objects: {}", project.object_count()?);
for obj in project.objects()? {
    let obj = obj?;
    println!("  Object: {:?}", obj.name()?);
}

§Architecture

The crate is organized in layers:

  • Address translation (addressmap::AddressMap): Converts VAs/RVAs to file offsets using section tables from goblin.
  • VB structures (vb): View types for each structure in the VB6 internal format (VBHeader, ProjectData, ObjectTable, etc.).
  • P-Code decoding (pcode): Opcode tables, operand types, and a streaming instruction iterator.
  • High-level API (VbProject): Ties everything together into a convenient exploration interface.

§Design

All structure types borrow from the original file byte slice (&'a [u8]). Accessor methods read directly from the underlying buffer using little-endian byte decoding.

§Robustness contract

VB6 binaries from the wild include malware samples that may be truncated, have inconsistent structure-size fields, or carry intentionally adversarial VAs. Every public API in this crate falls into one of three behavioural categories — pick the one that matches your call site:

§1. Fail-loud at the byte boundary (primitive accessors)

Every fixed-offset accessor like VbHeader::project_data_va, ProcDscInfo::frame_size, or VbObject::name_bytes returns Result<T, Error>. The crate’s underlying byte readers are panic-free (no unwrap, no panicking indexing, no unchecked arithmetic); out-of-buffer reads surface as Error::Truncated and offset overflows as Error::ArithmeticOverflow. Use ? to propagate.

§2. Skip-and-continue (per-entry iterators)

Iterators like InstructionIterator, PCodeMethodIterator, and ConstPoolIter yield Item = Result<T, Error> per entry — they emit one Err per malformed row and keep going, so a single bad entry does not poison the whole sweep. Match on each Item to pull successes, log failures, or stop early on first error per your policy. Iteration ends only when the underlying byte stream is exhausted (or a structural-truncation Err is yielded — most iterators continue past per-entry errors).

§3. Silent fail-soft (high-level joins)

High-level convenience methods like VbObject::events, VbProject::code_entrypoints, and the pcode::calltarget resolvers eagerly collect from one or more underlying iterators and silently drop malformed rows (filter_map(|r| r.ok())) so the returned Vec is “everything that parsed”. This matches malware-analysis triage: one corrupt control should not block enumeration of the other 50. Enable the optional tracing feature to capture the dropped rows as target = "visualbasic::dropped" warn events.

§4. Recognition-time errors at VbProject::from_bytes

Parse failures during the recognition phase are classified by Error::recognition_failure into one of:

Consumers tagging files as “VB6 or not” should match on this classification to silently skip non-VB6 files and only log the TruncatedContainer cases.

§Adversarial input invariants

The crate is built under the lint set clippy::{unwrap_used, expect_used, panic, arithmetic_side_effects, indexing_slicing} — every byte read goes through a checked helper, every offset computation uses checked_add / wrapping_add / saturating_add depending on semantics, and every slice access uses .get(...) rather than []. No input byte sequence can panic this parser. Tests are exempt from these lints.

Re-exports§

pub use addressmap::AddressMap;
pub use error::Error;
pub use error::RecognitionFailure;
pub use project::CodeEntrypoint;
pub use project::CompilationMode;
pub use project::DiagnosticKind;
pub use project::DiagnosticSeverity;
pub use project::EntrypointKind;
pub use project::MethodEntry;
pub use project::PCodeMethod;
pub use project::ParseDiagnostic;
pub use project::VbControl;
pub use project::VbObject;
pub use project::VbProject;

Modules§

addressmap
PE address translation utilities.
entrypoint
VB6 entry point detection.
error
Error types for VB6 P-Code parsing.
pcode
P-Code bytecode decoding.
project
High-level VB6 project exploration API.
vb
VB6 internal structure parsers.