Skip to content

DaCodeChick/VBDecompiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

69 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VBDecompiler

A Ghidra-style decompiler for Visual Basic 5/6 executables, built with a Rust decompilation engine and Qt 6 GUI.

Features

  • Multi-format Support: Analyze .exe, .dll, and .ocx VB binaries
  • Dual Disassembly: View both P-Code (VB intermediate language) and x86 native code
  • Packer Detection: Automatic detection of UPX, ASPack, PECompact, and other common packers
  • Ghidra-style UI: Familiar workspace with symbol browser, type browser, and function call trees
  • Smart Symbol Naming: Automatic FUN_ and DAT_ naming conventions
  • VB6 Decompilation: Reconstruct original Visual Basic 6 source code
  • Memory-Safe Core: Rust implementation for reliable, crash-free decompilation
  • Parallel Decompilation: Multi-threaded processing with Rayon scales to all CPU cores
  • Comprehensive Analysis:
    • Disassembly listing with bytes, stack depth, mnemonic, and IL instruction columns
    • Defined strings browser
    • Global data viewer
    • Function table with cross-references
    • Equates and constants

Architecture

Technology Stack

  • Core Engine: Rust 2021 (memory-safe decompilation logic with parallel processing)
  • GUI Framework: C++23 + Qt 6 (Widgets, Core, Gui)
  • FFI Layer: C bindings bridging Rust core to C++ GUI
  • Build System: CMake 3.20+ (C++/Qt) + Cargo (Rust)
  • Disassembly: iced-x86 for professional x86/x64 disassembly
  • Packer Detection: Entropy analysis and signature-based detection (goblin + entropy crate)
  • Concurrency: Rayon for data-parallel method decompilation
  • Target Platforms: Windows, Linux, macOS

Hybrid Architecture

VBDecompiler uses a unique hybrid architecture combining Rust's safety with Qt's mature GUI:

┌─────────────────────────────────────────┐
│         Qt6 GUI (C++)                   │
│    - MainWindow and UI components       │
└──────────────────┬──────────────────────┘
                   │ C FFI
                   ↓
┌─────────────────────────────────────────┐
│      Rust Decompilation Core            │
│  ┌───────────────────────────────────┐  │
│  │  vbdecompiler-ffi (C bindings)    │  │
│  └──────────────┬────────────────────┘  │
│                 ↓                        │
│  ┌───────────────────────────────────┐  │
│  │  vbdecompiler-core                │  │
│  │  - PE parsing (goblin)            │  │
│  │  - Packer detection (entropy)     │  │
│  │  - VB5/6 structure parsing        │  │
│  │  - P-Code disassembler            │  │
│  │  - x86 disassembler (iced-x86)    │  │
│  │  - IR system                      │  │
│  │  - P-Code to IR lifter            │  │
│  │  - VB6 code generator             │  │
│  └───────────────────────────────────┘  │
│                                          │
│  ┌───────────────────────────────────┐  │
│  │  vbdecompiler-cli (optional)      │  │
│  │  - Standalone command-line tool   │  │
│  └───────────────────────────────────┘  │
└─────────────────────────────────────────┘

Project Structure

VBDecompiler/
├── CMakeLists.txt              # C++ build configuration
├── Cargo.toml                  # Rust workspace configuration
├── crates/                     # Rust crates
│   ├── vbdecompiler-core/      # Core decompilation engine
│   ├── vbdecompiler-cli/       # Command-line tool
│   └── vbdecompiler-ffi/       # C FFI bindings
├── src/
│   ├── main.cpp                # Application entry point
│   └── ui/                     # Qt UI components
│       └── MainWindow.{h,cpp,ui}
├── include/
│   └── vbdecompiler_ffi.h      # C FFI header
├── tests/                      # C++ unit tests
└── docs/                       # Documentation

Building

Prerequisites

  • Rust 1.70+ (cargo, rustc)
  • CMake 3.20 or later
  • Qt 6.5+ (Core, Widgets, Gui modules)
  • C++23 compatible compiler:
    • GCC 13+
    • Clang 16+
    • MSVC 2022 (17.6+)

Build Instructions

# Clone the repository
git clone https://github.com/yourusername/VBDecompiler.git
cd VBDecompiler

# Rust builds automatically during CMake build
mkdir build && cd build

# Configure with CMake (builds Rust library automatically)
cmake ..

# Build
cmake --build .

# Run GUI
./bin/vbdecompiler

# Or use the CLI tool directly
cargo run --package vbdecompiler-cli -- decompile <file.exe>

Linux/macOS

# Install dependencies
# Ubuntu/Debian:
sudo apt install qt6-base-dev cmake g++-13 cargo

# Arch Linux:
sudo pacman -S qt6-base cmake gcc rust

# macOS (Homebrew):
brew install qt@6 cmake rust

# Build
mkdir build && cd build
cmake -DCMAKE_CXX_COMPILER=g++-13 ..
make -j$(nproc)

Windows

# Install Rust from https://rustup.rs/
# Install Qt 6 from https://www.qt.io/download
# Install Visual Studio 2022 with C++ workload

# Build using Visual Studio Developer Command Prompt
mkdir build && cd build
cmake -G "Visual Studio 17 2022" ..
cmake --build . --config Release

Usage

GUI Application

Launch the Qt6 GUI application:

# From build directory
./bin/vbdecompiler

# Or from install location
vbdecompiler

Opening a File:

  1. Click File → Open or use the toolbar button
  2. Select a VB5/6 executable (.exe, .dll, or .ocx)
  3. The decompiler will parse the binary and populate the UI

UI Overview:

The VBDecompiler workspace consists of:

Left Panel:

  • Symbol Tree: Navigate functions, data, and strings
  • Type Manager: Browse VB types and structures

Center Panel (Tabbed):

  • Disassembly Listing: Main disassembly view with address, bytes, stack depth, mnemonic, and IL instruction columns
  • Decompiler View: Reconstructed VB6 source code

Right Panel:

  • Function Call Tree: Incoming/outgoing calls hierarchy (Ghidra-style)
  • References Panel: Cross-references (xrefs)

Bottom Tabs:

  • Defined Strings: String literals table
  • Data: Global variables listing
  • Functions: Function table with addresses
  • Equates: Constants and enums

Switching Between P-Code and x86 Views:

Use the View menu or toolbar button to toggle between P-Code (VB intermediate language) and x86 native assembly views.

Command-Line Tool

The CLI provides full headless operation for batch processing, CI/CD integration, and scripting.

Installation

Option 1: System-wide install via Cargo

cargo install --path crates/vbdecompiler-cli

Option 2: Build and use locally

cargo build --release --package vbdecompiler-cli
./target/release/vbdc --help

Option 3: CMake install (includes both GUI and CLI)

mkdir build && cd build
cmake .. && make
sudo make install  # Installs vbdc to /usr/local/bin

Available Commands

Decompile - Full decompilation to VB6 source code

# Decompile to stdout
vbdc decompile input.exe

# Output to file
vbdc decompile input.exe --output output.vb

# Output to directory (auto-generates filename from input)
vbdc decompile input.exe --output ./output/

# JSON format (for programmatic integration)
vbdc decompile input.exe --format json --output result.json

# IR format (intermediate representation)
vbdc decompile input.exe --format ir --output output.ir

Info - Analyze PE structure and detect packers without decompiling

# Human-readable output
vbdc info input.exe

# Detailed analysis (includes sections, imports, etc.)
vbdc info input.exe --detailed

# JSON output (for parsing in scripts)
vbdc info input.exe --format json

Check-Packer - Detect if executable is packed

# Verbose output with confidence and unpack instructions
vbdc check-packer packed.exe

# Quiet mode (just prints packer name, for scripting)
vbdc -q check-packer packed.exe

# Exit codes: 0 = unpacked, 1 = packed (useful in shell scripts)
if vbdc check-packer input.exe >/dev/null 2>&1; then
    echo "File is not packed"
else
    echo "File is packed, unpack before decompiling"
fi

Disasm - P-Code disassembly only (no decompilation)

# Output to stdout
vbdc disasm input.exe

# Show hex bytes
vbdc disasm input.exe --hex

# Save to file
vbdc disasm input.exe --output disasm.txt

Completions - Generate shell completions

# Bash
vbdc completions bash > ~/.local/share/bash-completion/completions/vbdc

# Zsh
vbdc completions zsh > ~/.zsh/completions/_vbdc

# Fish
vbdc completions fish > ~/.config/fish/completions/vbdc.fish

# PowerShell (Windows)
vbdc completions powershell > vbdc.ps1

Global Options

  • -v, --verbose - Enable verbose logging (shows debug information)
  • -q, --quiet - Quiet mode (errors only, useful for scripting)
  • -h, --help - Print help information
  • -V, --version - Print version information

Batch Processing Example

Process multiple VB executables in a directory:

#!/bin/bash
for exe in *.exe; do
    echo "Processing $exe..."
    
    # Check if packed
    if vbdc -q check-packer "$exe" 2>/dev/null; then
        echo "  Skipping (packed): $exe"
        continue
    fi
    
    # Decompile
    vbdc decompile "$exe" --output "decompiled/${exe%.exe}.vb" \
        && echo "  Success: $exe" \
        || echo "  Failed: $exe"
done

Supported Packer Detection

The CLI automatically detects these packers with high confidence:

  • UPX (Ultimate Packer for eXecutables)
  • ASPack (Advanced Software Packer)
  • PECompact (PE file compressor)
  • Themida (Advanced protection system)
  • FSG (Fast Small Good packer)
  • Petite (Small PE compressor)
  • MEW (Magic Executable Wrapper)
  • NSPack (NorthStar PE Packer)

Detection methods:

  1. Section signatures (95% confidence) - Detects characteristic section names
  2. Entropy analysis (70% confidence) - Identifies compressed/encrypted data
  3. Import table (50% confidence) - Checks for minimal imports typical of packers

Programmatic API (Rust)

Add to your Cargo.toml:

[dependencies]
vbdecompiler-core = { path = "./crates/vbdecompiler-core" }

Example usage:

use vbdecompiler_core::{Decompiler, DecompilerOptions};
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = DecompilerOptions::default();
    let decompiler = Decompiler::new(options);
    let result = decompiler.decompile_file(Path::new("input.exe"))?;
    
    println!("Decompiled {} methods", result.methods.len());
    for method in result.methods {
        println!("Method at 0x{:08x}:\n{}", method.address, method.code);
    }
    Ok(())
}

Testing

Rust Core Tests

The Rust decompilation core has comprehensive unit tests:

# Run all Rust tests
cargo test --all

# Run with output
cargo test --all -- --nocapture

# Run specific crate tests
cargo test -p vbdecompiler-core

# With coverage (requires cargo-tarpaulin)
cargo tarpaulin --all --out Html

C++ Tests

C++ tests focus on the X86 disassembler component:

# Build tests
cd build
cmake --build . --target test_x86

# Run tests
./bin/test_x86

Integration Testing

To test the full GUI → FFI → Rust pipeline:

  1. Build the complete project:

    mkdir build && cd build
    cmake .. && cmake --build .
  2. Run the GUI:

    ./bin/vbdecompiler
  3. Load a test VB executable (P-Code compiled VB5/6 binary)

  4. Verify:

    • No crashes during file loading
    • Decompiled output appears in the center panel
    • Symbol tree populates with discovered methods
    • Log output shows parsing progress

Sample Test Files

The project includes sample VB executables for testing:

  • tests/samples/simple_pcode.exe - Basic P-Code executable
  • tests/samples/forms_app.exe - VB app with forms
  • tests/samples/native_code.exe - Native-compiled VB (x86 only)

Note: These are not included in the repository due to size. You can create test binaries using Visual Basic 6.0 IDE with "Compile to P-Code" option.

VB Binary Support

Supported Dialects

  • Visual Basic 5 (VB5)
  • Visual Basic 6 (VB6)

Compilation Modes

  • P-Code: VB bytecode executed by MSVBVM60.DLL runtime
  • Native Code: Compiled to x86 machine code

File Formats

  • .exe - VB executables
  • .dll - VB DLLs
  • .ocx - ActiveX controls

Detection

The decompiler automatically detects:

  • VB5/VB6 signature (VB5! header)
  • P-Code vs native compilation
  • Packed/compressed executables:
    • UPX (Ultimate Packer for eXecutables)
    • ASPack (commercial packer)
    • PECompact (commercial packer)
    • Themida/WinLicense (advanced protection)
    • FSG, Petite, MEW, NSPack (other common packers)
    • Unknown packers via entropy analysis

Packed Executables

If the decompiler detects a packed executable, it will display an error message with unpacking instructions. For UPX-packed files:

# Install UPX from https://upx.github.io/
# Unpack the executable
upx -d packed.exe -o unpacked.exe

# Then decompile with CLI or GUI
vbdc decompile unpacked.exe
# or
./vbdecompiler unpacked.exe

The packer detection system uses:

  • Section name analysis: Identifies packer signatures (e.g., "UPX0", ".aspack")
  • Entropy analysis: Detects compressed/encrypted sections (Shannon entropy > 7.2)
  • Import table analysis: Flags suspiciously minimal imports

For other packers, consult the specific unpacker tool or use universal unpackers.

Documentation

Research References

Based on research from:

Contributing

Contributions welcome! Please read CONTRIBUTING.md for guidelines.

License

GPL-3.0 License - see LICENSE file for details.

Acknowledgments

  • Inspired by Ghidra reverse engineering framework
  • VB structure definitions from Semi-VB-Decompiler project
  • VB community reverse engineering research

About

Visual Basic decompiler

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors