2026-04-16 04:45:22 -07:00
yes
2026-04-15 22:24:44 -07:00
yes
2026-04-16 04:45:22 -07:00
yes
2026-04-16 04:45:22 -07:00
yes
2026-04-15 22:24:44 -07:00
yes
2026-04-16 04:45:22 -07:00
yes
2026-04-16 04:45:22 -07:00

Paralogue MITM Toolkit

Man-in-the-middle proxy and protocol analysis toolkit for Operation Lovecraft: Fallen Doll (Paralogue). Intercepts, decodes, modifies, and injects game network traffic in real time via a desktop GUI.

Features

  • Real-time packet inspector — decoded protobuf messages with JSON syntax highlighting and hex dump
  • Bidirectional wire decryption — ChaCha20 key extraction via Frida, proxy-side decrypt/re-encrypt
  • Packet modification — frame-aware S->C rewriter with pluggable modifier callbacks
  • Packet injection — send custom or replayed packets in both C->S and S->C directions
  • Full type mapping — all 191 dispatch-table msg_ids resolved to protobuf type names via Frida GetTypeName()
  • ImGui GUI with 6 tabs: Packets, Config, Session, Wire, Dispatch, Composer

Requirements

  • Python 3.12+ (tested on 3.13)
  • Windows 10/11
  • Frida (pip install frida-tools)
  • imgui-bundle (pip install imgui-bundle)
  • cryptography (pip install cryptography)
  • protobuf (pip install protobuf)
pip install frida-tools imgui-bundle cryptography protobuf

Quick Start

cd frida_hooks
run_gui.bat
  1. GUI opens with proxy listening on ports 11001 (game) and 18801 (HTTP dispatch)
  2. Click "Launch Game (Steam)" or launch via Steam manually
  3. Frida auto-attaches, hooks installed, redirect active
  4. Log in — packets stream into the Packets tab
  5. Toggle modifiers in the Config tab
  6. Click any packet → Send tab → "Replay Original" or "Open in Composer"

Headless mode (CLI)

cd frida_hooks
run_mitm.bat                  :: normal passthrough
run_mitm.bat --inject-items   :: with all modifiers active
run_mitm.bat --no-decoder     :: proxy only, no Frida

Re-extract type names (after game update)

:: Game must be running
cd frida_hooks
run_extract_types.bat

Updates dispatch_type_names.json, known_msg_ids.json, and factory_to_type.json.

Architecture

┌────────────┐    ┌─────────────────────┐    ┌──────────────┐
│  Game      │◄──►│  Proxy (port 11001) │◄──►│  Real Server │
│  Client    │    │  ┌───────────────┐  │    │  3.33.185.193│
│            │    │  │ WireRewriter  │  │    │              │
│  Frida ────┼────┤  │ S->C + C->S   │  │    │              │
│  hooks     │    │  └───────────────┘  │    │              │
└────────────┘    │  ┌───────────────┐  │    └──────────────┘
                  │  │ Modifier Chain│  │
                  │  └───────────────┘  │
                  └──────────┬──────────┘
                             │ SharedState
                  ┌──────────▼──────────┐
                  │   ImGui GUI         │
                  │   (main thread)     │
                  └─────────────────────┘

Threading model

  • Main thread: ImGui render loop at ~60fps
  • Background daemon thread: asyncio event loop running the TCP proxy, Frida bridge, and injection consumer
  • SharedState: thread-safe bridge (deque for packets, Lock for config, inject_queue for packet injection)

Encryption

The game uses ChaCha20 stream cipher with a shared key+nonce for both directions but independent byte counters:

Offset Field Usage
+0x68 key ptr 32B ChaCha20 key (shared)
+0x78 nonce ptr 12B nonce (shared)
+0x88 EVP ctx encrypt (C->S)
+0x90 EVP ctx decrypt (S->C)
+0x98 counter encrypt byte offset (C->S)
+0xA0 counter decrypt byte offset (S->C)

The proxy uses WireRewriter per direction to decrypt→modify→re-encrypt. ChaCha20 XOR involution means identity transforms produce byte-identical output.

Wire format

[2B big-endian prefix N][N-byte PacketHead protobuf][body_len bytes body]

PacketHead fields: msg_id, body_len, packet_id (request-response correlation), seq_id, flag, total_pack_count.

GUI Tabs

Packets

Real-time scrolling table of decoded messages. Filter by direction, source (Frida/wire), msg_id, or type name. Click a row to expand:

  • Tree — recursive protobuf field viewer
  • JSON — syntax-highlighted JSON via TextEditor
  • Hex — formatted hex dump with ASCII sidebar
  • Send — replay original or open in Composer

Config

Toggle modifiers individually:

  • Card Bag Expand — CardBagOpenRsp.rets → 0..2000 (unlock experiments)
  • Inject Blueprints — add 11000..11999 to bag (lootbox items)
  • Role Attrs Saturate — max affection, dilation, unlock all roles
  • Inject Bag Items — dense fill across cloth/card/normal ranges
  • Unlock Functions — populate PlayerMainDataRsp.unlockFunctions

Parameter sliders for card range, attr values. Auto-saves to gui_config.json.

Session

Session key/nonce, game PID, Frida status (color-coded), proxy ports, dispatch summary, packet counts. Action buttons:

  • Restart Frida — reattach after game relaunch
  • Launch Game (Steam) — opens via steam://rungameid/2701680

Wire

Raw encrypted traffic hex viewer with timestamps and direction arrows.

Dispatch

All 191 msg_id → protobuf type mappings. Green = pinned (resolved), red = unknown. Searchable by type name.

Composer

Compose and send custom protobuf packets:

  1. Select type from dropdown (all 191 dispatch types)
  2. Edit JSON in syntax-highlighted editor
  3. Choose direction (C->S / S->C)
  4. Click Send

Files

File Purpose
frida_hooks/paralogue_gui.py ImGui GUI application
frida_hooks/paralogue_mitm.py Core proxy + Frida bridge + WireRewriter
frida_hooks/paralogue_decoder.py Protobuf framing, identification, parsing
frida_hooks/protocol_decoder.js Frida hooks for decrypt/encrypt wrappers
frida_hooks/redirect_connect.js Frida ws2_32!connect redirect hook
frida_hooks/dispatch_dump.js Frida dispatch table walker
frida_hooks/extract_type_names.js Frida GetTypeName() extraction
frida_hooks/item_table_dump.js Frida bag item subsystem walker
frida_hooks/paralogue_net_full.proto 239-message protobuf schema
frida_hooks/paralogue_net_full_pb2.py Compiled protobuf module
frida_hooks/dispatch_type_names.json msg_id → type name (ground truth, 191 entries)
frida_hooks/factory_to_type.json vtable → type name (stable across runs)
frida_hooks/known_msg_ids.json Merged msg_id → type cache
frida_hooks/gui_config.json Persisted GUI modifier toggles
frida_hooks/run_gui.bat GUI launcher
frida_hooks/run_mitm.bat CLI launcher
frida_hooks/run_extract_types.bat Type extraction launcher
RESEARCH.md Detailed protocol research notes

Game Data Model

Bag items (BagItemFullS2C, msg_id 1036)

ID range Category Description
0-999 Experiments/Cards Unlocked via CardBagOpen
11000-11999 Pack/Blueprints Lootbox items (open → grant card)
20000-28999 Card/Normal Collectibles
31000-31999 Cloth Outfit pieces
40000-40999 Normal Misc items
99000-99999 Money Currencies (with counts)

Experiments

  • Stored as client-side learn_cards collection (persisted on disk)
  • Updated incrementally via CardBagOpenRsp.rets[].card_id
  • UI filters by client DataTable (invalid IDs silently dropped)
  • Unlock all: enable "Card Bag Expand" modifier, open one blueprint

Roles (RoleListFullS2C, msg_id 1202)

Per-role data: name, is_unlock, favor_lv, worn_clothes[], preset_clothes[], attrs{}, appearance, clothes_colors.

License

Research and educational purposes only. Not affiliated with the game developers.

S
Description
No description provided
Readme
15 MiB
0 Stars 1 Watchers 0 Forks
Languages
C++ 99.8%
Python 0.2%