Files

7.2 KiB

Ghostwire architecture

Two ways to run the same code

python -m whatsapp_suite runs the editable source package. python whatsapp.py runs its generated portable distribution through the same CLI.

The builder stores the maintained modules, fixtures and selected assets in a compressed archive. The launcher verifies its payload, imports Python modules from memory, and extracts only the native helper needed for a live operation into a hash-verified cache beside the bundle. A C++ compiler is needed to change native code, not to run the portable file.

Live JavaScript execution

sequenceDiagram
    participant CLI as Python CLI
    participant DLL as Native helper
    participant WV as Existing WhatsApp WebView
    CLI->>CLI: Detect host and UI thread; verify helper
    CLI->>DLL: Temporary Windows hook + shared request
    DLL->>DLL: Discover and validate native layout
    DLL->>WV: ExecuteScriptAsync
    WV-->>DLL: JavaScript result
    DLL-->>CLI: Shared result packet
    CLI->>CLI: Release hook, mappings and handles

Python calls Windows APIs through ctypes. A WH_GETMESSAGE hook loads the helper on WhatsApp's UI thread. A thread message wakes it; a shared mapping carries a bounded request and result.

The helper scans the loaded WebView component for relocation-free code fingerprints and a matching vtable layout, then locates the existing object and validates its script-execution method. This avoids fixed module-relative function addresses. Compiler/object-field and interface ABI assumptions remain.

The hook is temporary. Normal exports and probes record cleanup of the hook, mapping, process handles and helper. Native failures are not evidence that a different layout is safe.

Read, search and send

Operation Data path Boundary
ZIP export App database getter → app row decoder → paginated records → ZIP Local rows; no atomic snapshot, phone sync or media download
Old-message read Timestamp scan → five oldest rows → app decoder Bounded scan; not limited to loaded chat models
Contact export Local contact table → selected identity/name/business fields May contain separate PN/LID records
Desktop search Existing app message search → bounded metadata Search scope comes from the app
Saved-export search Python JSON/JSONL parsing and normalization Does not need the app
Self-message Resolve own identity → guarded send → stored readback One fixed test message; no arbitrary-recipient CLI

Database text is decoded through WhatsApp's own JavaScript methods under the signed-in session. Failed row decodes remain explicit. Export publication refuses existing outputs and checks ZIP CRCs.

Listener and delivery

flowchart LR
    M["Loaded message collection"] --> J["JS observer and decoded queue"]
    J --> N["UI-thread native timer"]
    N --> H["WinHTTP worker"]
    H --> T["HTTPS target or loopback receiver"]
    T --> A["HTTP 2xx"]
    A --> Q["Remove acknowledged queue entries"]
    R["Optional Windows minute task"] --> I["Restore after app restart"]
    I --> J

The JavaScript producer observes message collection events, obtains stored rows through the app decoder, and queues bounded message events. It does not contain transport credentials. A UI-thread timer executes short queue scripts; a worker performs HTTP delivery outside that UI thread.

Direct HTTPS uses certificate validation and a token header. Loopback mode posts to a local receiver. Proxies and redirects are disabled. Native WinHTTP supplies the outbound transport; direct JavaScript localhost requests were blocked by WhatsApp's CSP during testing, and the implementation does not weaken CSP.

HTTP 2xx triggers queue acknowledgement. Failures leave records for retry. A consumer must deduplicate IDs; this is not exactly-once delivery. The built-in local receiver commits SQLite data before acknowledgement.

The installer exits after setup. The native relay retains a module reference so timer/worker callbacks remain valid. Stop cancels observation/timers and releases WebView references; an idle DLL remains loaded until app exit.

Restoration and configuration

WhatsApp process exit destroys the listener and native relay. Automatic restoration is a separate capability:

Mode Bootstrap Lifetime
Direct HTTPS with --auto-restore Per-user Windows task invokes webhook ensure every minute Short Python checks; no continuous local server
Loopback receiver with --restore-config Receiver checks every five seconds Receiver must remain running
Optional watch Python restoration loop Watcher remains running

The task runs as the logged-in user with limited privileges. It stores paths to Python, the bundle and configuration; moving them breaks that registration. Direct restoration recovers a current-user DPAPI-protected token from the configuration. The bundle is portable, but that protected configuration is tied to the Windows user/machine.

Reinstallation reconciles qualifying loaded models since the saved start timestamp; it does not perform complete database catch-up. In-memory queues can be lost on exit, and messages in startup/polling gaps are not guaranteed to be delivered. See the webhook guide for schema and limits.

Source map

Layer Files
Command dispatch and tests cli.py, runner.py, tests/
Shared resources/cache common.py
Windows orchestration desktop.py, live.py, native_search.py
Data operations history.py, zip_export.py, contacts_export.py, exports.py, self_message.py
Listener orchestration webhook.py, assets/webhook_listener.js
Native implementations native/math_probe.cpp, search_probe.cpp, webhook_probe.cpp, core_discovery.h
Portable packaging build_whatsapp_bundle.py, generated whatsapp.py

All Python filenames above are under whatsapp_suite/. See contributing for extension steps and hash updates.

Compatibility and security boundaries

The tested Desktop build is 2.2639.100.0. Other builds produce advisory metadata/warnings and are attempted, but dynamic address discovery does not imply compatibility with every future compiler/object layout. Changed layouts can fail or cause process instability.

The observed bridge uses documented Windows loading and WebView execution APIs. It does not demonstrate memory corruption, privilege escalation or broken encryption. The overall integration remains reverse-engineered process instrumentation: WhatsApp does not document these internal module calls as an external automation API. This is not a complete security audit.

Passwords/passkey private keys and media download are not implemented features. Core commands use no CDP or UI automation; optional research tools have separate transports. Hashes establish integrity, not publisher identity.

See validation for evidence, security for private-data handling, and Microsoft's Windows hook and WebView JavaScript documentation for the public APIs.