103 lines
7.2 KiB
Markdown
103 lines
7.2 KiB
Markdown
# 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
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```mermaid
|
|
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](WEBHOOKS.md) 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](../CONTRIBUTING.md) 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](VALIDATION.md) for evidence, [security](../SECURITY.md) for private-data handling, and [Microsoft's Windows hook](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw) and [WebView JavaScript](https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/javascript) documentation for the public APIs.
|