Web Protocol Recovery
Role
Turn hostile web clients into stable protocol collectors.
This skill is not a browser automation skill.
This skill is a protocol recovery skill.
Default posture:
- start every fresh target without upstream evidence with an ordinary Chrome baseline before any CloakBrowser escalation
- find the real request
- identify the true changing state
- rebuild that state offline
- deliver a browser-free Python collector, plus a local JS parameter helper only when truly needed
Trigger Boundary
Use this skill when the user wants a complete browser-free collector or protocol replay, not merely one missing component.
Trigger when:
- the task asks to build, repair, or stabilize a crawler/collector/replay script outside the browser
- several moving parts must be recovered together, such as signature + bootstrap cookie + response decode + transport wrapper
- the target is WebSocket, GraphQL, protobuf, msgpack, encrypted response, dynamic-font decode, or stateful session protocol
- another skill or the user already supplied real request samples, call stacks, signer formulas, fixed input-output samples, or response bodies and now asks for implementation
Do not trigger when:
- only the sign/token/header entry, script URL, function name, or call stack is unknown ->
camoufox-js-reverse
- only a Console/Snippets hook script is requested ->
browser-hook-snippets
- a known browser JS entry must be made to run in Node.js/vm/jsdom ->
env-patch
- the request is a compact Python + iv8 + requests script ->
iv8-web-reverse
- the task is whole-file AST deobfuscation or control-flow restoration ->
ast-deobfuscate
- the target is WeChat miniapp / WMPF runtime debugging ->
wechat-miniapp-reverse
Non-Negotiables
- Final delivery must be pure protocol: raw HTTP plus local signer, local decoder, or local bootstrap helper only.
- Every fresh target without upstream evidence must get a normal-Chrome baseline before writing the final collector.
- Use
js-reverse-mcp (starts in normal Chrome) for all ordinary JS reverse work.
- To switch to CloakBrowser at runtime: call
launch_browser with cloakBinaryPath pointing to the CloakBrowser binary.
- To switch back to normal Chrome: call
launch_browser with an empty cloakBinaryPath.
- Do not start CloakBrowser for ordinary signer, wrapper, decode, or request-diff work.
- Do not ship Playwright, Selenium, CDP page-driving, or submit-through-browser flows as the solution.
- Final delivery must run fully outside the browser: Python crawler scripts for collection, plus a local JS helper only for parameter, sign, token, or cookie reconstruction when Python porting is not yet the safest choice.
- Prefer Python for the collector and orchestration.
- Only keep a tiny isolated JS or WASM helper when a verified Python port is not yet cheaper, safer, or faster to maintain.
- Any JS helper must run locally without page driving,
document, window, manual clicks, browser profiles, or hidden browser dependencies.
- If browser tooling is used at all, use it only for recon and evidence gathering, never as a hidden dependency in the final collector.
- Automation is forbidden as the final answer, forbidden as a fallback answer, and forbidden as a disguised "temporary" delivery path.
- Recover one stable request before scaling pagination, concurrency, or submission.
- Every conclusion must be backed by artifacts: request samples, fixed-input helper outputs, cookies, headers, and replay proof.
- All reconnaissance artifacts such as downloaded JS, WASM, fonts, HTML, network exports, state snapshots, screenshots, traces, and fixed-input vectors must go under the generated project's root-level
js_reverse_cache/; create the project scaffold before saving target artifacts.
- Final collector code must live in the same dedicated protocol project directory using the bundled scaffold shape:
analysis/, collector/, js_reverse_cache/, tests/, README.md, and requirements.txt. Do not collapse the delivery into a single main.py except for a temporary throwaway probe saved under that project's js_reverse_cache/.
- Stay in one execution loop until you reach protocol delivery or hit a real external blocker.
Confirmation Checkpoints
Do not let protocol recovery expand from artifact analysis into live side effects without a short user confirmation. Pause before:
- using account-bound cookies, Authorization headers, session ids, private API keys, or paid/privileged data sources in live replay
- submitting verifier answers, CAPTCHA/behavior payloads, forms, mutations, orders, payments, messages, or any request that can change server state
- increasing from one stable proof request to pagination, concurrency, retries, long-running collection, or high-volume scraping
- saving or printing full raw cookies, tokens, Authorization values, request bodies, response bodies, decrypted payloads, or account-bound samples; default to minimal fields, hashes, lengths, or masked excerpts
- switching from evidence reuse to fresh browser reconnaissance because provided artifacts are insufficient; state the missing artifact first, then ask for permission to collect it
No pause is needed for offline fixed-input signer checks, local decoder tests, static source reading, or replay against user-provided mock/sample artifacts.
Startup Gate
Before any deep tool use on a fresh target, emit a short startup gate and fill it with current evidence.
Evidence reuse path:
- if the task arrives from another skill, or the user already supplied real requests, headers/cookies, call stacks, signer formulas, fixed input-output samples, or response bodies, do not redo browser availability checks just to satisfy the fresh-target gate
- for this path, confirm the artifact directory, classify the protocol family, declare the final collector shape, then implement and verify against the provided artifacts or live replay when allowed
Required checks:
- environment and tool sanity for fresh targets without upstream evidence
- run
scripts/check_reverse_env.py when local execution is available
- confirm whether
chrome-devtools-mcp and js-reverse-mcp (normal Chrome, switchable to CloakBrowser via launch_browser) are usable
- record the browser tier: normal Chrome first, CloakBrowser only after explicit escalation evidence
- if one tool is blocked, report the blocker before pretending the target is understood
- artifact directory discipline
- confirm the generated protocol project root has
js_reverse_cache/, or create/scaffold the project before saving dynamic materials
- save browser/network/source/state artifacts under the project's
js_reverse_cache/, and save final collector code under the same dedicated protocol project directory
- family triage
- classify the target first as
signer-gated, verifier-gated, decode-gated, or session-gated
- read
references/startup-triage-playbook.md before loading giant bundles
- if a rotating cookie appears important, read
references/cookie-provenance-playbook.md before hardcoding anything
- delivery intent
- state the intended final shape: pure Python, Python plus tiny JS helper, Python plus tiny WASM helper, or Python plus local bootstrap executor
- explicitly reject browser-backed fetches, browser profiles, and automation-driven replay as the final answer
Rule:
- if the startup gate is incomplete, the target is not yet understood
- if the classification changes after new evidence, restate the gate instead of silently drifting
What This Skill Optimizes For
- protocol-first reverse engineering
- Python-first delivery
- offline reproduction of dynamic state
- reusable collectors instead of one-off lucky requests
- generic methodology that transfers across similar targets
Reference Layout
The references/ directory is organized by purpose:
- root-level playbooks are generic pattern documents and reusable workflows
Rule:
- read generic pattern playbooks first
- abstract solved work back into generic patterns instead of storing site-specific folklore
Similarity Heuristics
Treat a target as belonging to the same family when one or more of these symptoms appear:
- page code mentions one endpoint but the wire uses another
- business code builds
token, sign, or m, but transport wrappers rewrite it before send
- the transport is GraphQL, WebSocket frames, protobuf, msgpack, or another structured envelope rather than plain JSON
- standard helper names such as
md5, btoa, atob, or sha1 produce nonstandard output
- the first request returns JavaScript, cookies, offsets, or font files instead of business data
- the page is public, but a bootstrap endpoint still returns a public key, config blob, nonce seed, or wrapper contract before list requests work
- only one page fails, often the last page
- the page text says login or
sessionid matters, and the answer differs per account
- the site ships a tiny side script or
.wasm that looks unrelated but actually seeds signing state
- the API returns strings, hints, glyphs, or fonts instead of the final numeric payload
- the response body is encoded, compressed, protobuf, msgpack, or split across multiple layers before it becomes usable data
- the same request succeeds once and then dies unless some hidden refresh state is regenerated
- list APIs work anonymously, but detail or submit APIs still reject without a different permission boundary
- empty filter values do not reproduce the visible tab because the page injects category or mode state before send
- a login or pairing step returns a ref, QR seed, public key, or client identifier before business frames become readable
- the target keeps one long-lived WebSocket alive with auth, ack, heartbeat, or reconnect frames that must stay in order
- media metadata arrives in one place, but the actual file replay or decryption needs a separately derived key
If the symptoms match, reuse the methodology even when the exact site and parameter names differ.
Operating Doctrine
Doctrine 1: Trust the wire, not the page text
- Real request paths beat page hints.
- Real headers beat visible business code.
- Real cookies beat guessed token stories.
- Real response shape beats archived notes.
Doctrine 2: The dynamic parameter is not always a signature
The real moving part may be:
- a cookie
- a page-specific header
- a transport envelope
- a server-returned JS bootstrap
- a dynamic font
- a WebAssembly export
- a transport wrapper rewrite
- a response-side decoder
- an account-bound session contract
Do not assume every hard target is solved by hunting a sign function.
Doctrine 3: Fixed-input validation beats naming
If a page helper is called md5 or btoa, prove it on fixed inputs before trusting the name.
Minimum standard for suspicious helpers:
- pick a fixed input such as
"abc" or a captured timestamp
- record browser output
- record local output
- compare intermediate values, not just final output
Doctrine 4: Narrow exceptions stay narrow
If only one page needs a special User-Agent, or only one request needs a rotated cookie, encode that exception explicitly.
Do not poison the entire collector with a fake "browser-only" conclusion.
Doctrine 5: Automation is not an acceptable crutch
When stuck, do more protocol work:
- diff requests
- extract inline scripts
- run bootstrap JS locally
- port helper logic
- instantiate WASM locally
- decode fonts locally
Do not fall back to browser automation as delivery.
Doctrine 6: Environment mismatch is evidence
When local output and live output disagree, treat the mismatch as evidence:
- compare fixed inputs
- compare side assets
- compare patched helpers
- compare environment branches
Do not hand-wave the mismatch away as "probably browser-only".
Doctrine 7: Delivery gates outrank convenience
If the only known path still depends on live page context, the task is not done.
- a browser profile is not a protocol artifact
- a hidden refresh click is not a collector
- an unexplained decoder is not acceptable handoff
Keep reversing until the moving parts are local, explicit, and testable.
Doctrine 8: Public does not mean unsigned
Anonymous pages still have protocol contracts.
- a public list may still require entry-route cookies
- a bootstrap endpoint may still return the key, config, or envelope seed
- list visibility does not prove detail or submit visibility
Treat anonymous access, envelope construction, and permission boundaries as separate questions.
Doctrine 9: Stateful streams are protocol, not browser magic
If the target only becomes readable after login, pairing, or a warm-up WebSocket exchange, the session transcript is part of the protocol.
- pairing or login bootstrap is not UI fluff
- handshake outputs are protocol artifacts
- heartbeats, ack frames, counters, and reconnect rules are part of the collector
Do not collapse a stateful stream problem into a fake single-request sign story.
Doctrine 10: Observer effect is real
Some targets get harder after you touch them.
- verifier-gated or behavior-sensitive flows may change once hooks, breakpoints, or monkey patches are installed
- capture one clean baseline request and response before invasive instrumentation
- prefer initiator stacks, request diffs, and narrow boundary hooks before broad global hooks
- if hooking changes the failure mode, treat that as evidence that your tooling is perturbing the target
Do not confuse hook-induced breakage with proof that the site is "browser-only".
Doctrine 11: Cookie provenance beats cookie superstition
When a cookie gates replay, prove where it came from:
Set-Cookie on a protocol response
document.cookie from page code
- server-returned challenge or bootstrap JS
- redirect wrappers, iframes, workers, or SDK side effects
- a derived header or token that only looks like a cookie problem
Do not hardcode a rotating business cookie before proving its writer and refresh path.
Minimal Intake
Start immediately if the user already provided enough evidence.
Otherwise ask only for the smallest missing set:
- target page URL, or
- target API URL, or
- site homepage plus collection goal, or
- captured request sample, or
- JS snippet, obfuscated bundle, cookie sample, sign sample, or packet capture
Only ask follow-ups that change implementation:
- target fields
- scope: single page, pagination, category, date range, or whole site
- output format: JSON, CSV, Excel, database, or API sink
- whether login is required
- whether incremental sync, dedupe, or resume is required
Universal Reverse Loop
Phase 0: Fingerprint before deep work
Classify the target before reading giant bundles:
- decoy endpoint vs real endpoint
- wrapper rewrite vs visible param
- patched helper vs standard helper
- signer-gated vs verifier-gated vs decode-gated vs session-gated
- bootstrap asset vs direct data API
- plain JSON vs GraphQL vs WebSocket vs binary envelope
- single-shot replay vs stateful session with pairing, auth, or warm-up frames
- direct response vs encoded response vs glyph-mapped response
- page-specific exception vs whole-flow exception
- session-bound vs anonymous
- clean-baseline-first vs trace-first vs decode-first vs transcript-first
- rotating-cookie provenance known vs unknown
- JSVMP or heavy obfuscation vs normal packed bundle
Browser tier rule:
js-reverse-mcp starts in normal Chrome; it is the default for all ordinary JS reverse work
- CloakBrowser is activated at runtime via
launch_browser({cloakBinaryPath: "..."})—no separate MCP server needed
- when no fingerprint evidence exists, use
js-reverse-mcp in normal-Chrome mode for everything
Goal:
- choose the smallest next proof and the least destructive first instrument, not the biggest code dump
Phase 1: Identify the true request path
- follow redirects
- inspect wrapper pages and compatibility pages
- separate visible page routes from real wire routes
- map bootstrap requests, list requests, detail requests, submission requests, and risk-control requests
- detect whether one endpoint serves both bootstrap and final data in separate phases
Deliverable for this phase:
- one confirmed request that is definitely on the real business path
Phase 2: Classify the moving parts
For the real request, classify each changing field:
- static header
- rotating header
- static cookie
- rotating cookie
- timestamp
- nonce or random fragment
- signed body or query
- transport envelope, operation name, or message type
- compressed or binary response format
- decode key, glyph map, or response-side transform
- encrypted response
- page-specific exception
- account-bound session dependency
- bootstrap artifact dependency
- login or pairing bootstrap artifact
- session key schedule or exported secret material
- heartbeat, ack, counter, or message-tag state
- media-key derivation or side-channel download secret
Goal:
- separate what must be reproduced from what is just noise
Phase 3: Locate the canonical mutation point
Look in this order:
- transport wrappers such as
$.ajaxSetup, beforeSend, fetch wrappers, interceptors
- bootstrap side scripts and inline payloads
- page-exposed helper functions
- WebAssembly exports
- server-returned JS challenges
- response-side refresh fields that seed the next request
- handshake transcripts, frame serializers, binary node encoders, protobuf parsers, or session key schedules
Rule:
- the canonical mutation point is where the wire payload actually changes, not where the business code first creates a placeholder
Phase 4: Rebuild the moving parts offline
Choose the cheapest valid offline shape:
- pure Python
- Python plus isolated JS signer
- Python plus minimal local JS or WASM helper
- Python plus local challenge bootstrap executor
- Python plus local font decoder
Never add browser automation to the final path.
Phase 5: Prove repeatability
Do not call it solved until:
- the same logic succeeds at least 2 to 3 times
- pagination advances correctly
- final fields are complete
- dynamic state regenerates correctly
- account-bound constraints are documented
Pattern Atlas
Pattern A: The endpoint on the page is fake
Symptoms:
- page code hooks
/api/match/...
- wire uses
/api/question/... or another path
- browser request succeeds but replaying the visible path fails
Action:
- trust the network path
- trace request initiators
- document the decoy path
- code against the live path only
Pattern B: The business param is a decoy
Symptoms:
- page code builds
token
- wire sends
m, f, or another field
- request wrapper mutates data before send
Action:
- reverse the wrapper first
- diff business-layer params against final payload
- rebuild the wrapper logic, not the decoy field
Pattern C: Standard helper is patched
Symptoms:
md5, btoa, atob, sha1, or similar names exist
- local reproduction with standard libraries does not match browser output
Action:
- freeze fixed test vectors
- port the exact helper implementation
- verify helper outputs before using them in requests
Pattern D: First response is not data, but bootstrap
Symptoms:
- first request returns JS,
Set-Cookie, offset scripts, or challenge tokens
- replay works only after the bootstrap response is processed
Action:
- treat bootstrap as part of the protocol contract
- execute or emulate it locally
- carry resulting cookies or globals into the next request
Pattern E: Only one page breaks
Symptoms:
- pages 1 to 4 work
- page 5 fails or returns hints, strings, or anti-bot signals
Action:
- diff headers and cookies by page
- test page-specific
User-Agent, referer, or ordering rules
- encode the exception narrowly
Pattern F: Answer or data is account-bound
Symptoms:
- page text mentions
sessionid
- different accounts produce different sums or answers
- submit works only with the same session that collected the data
Action:
- make
sessionid explicit in the collector
- keep fetch and submit under the same account
- verify with the same session before blaming signer logic
Pattern G: Tiny side assets carry the whole signer
Symptoms:
.wasm, /offset, challenge JS, or font files appear trivial
- main bundle is noisy but side asset changes output decisively
Action:
- inspect side assets early
- instantiate WASM locally
- execute bootstrap JS locally
- decode fonts locally
Pattern H: Dynamic fonts hide the payload
Symptoms:
- numeric values appear as glyphs or meaningless text
- response includes font URLs or embedded font data
Action:
- fetch the font asset
- derive the codepoint-to-digit map
- decode the payload locally
Pattern I: One-shot verifier, captcha, or click challenge
Symptoms:
- next request only works after a verification step
- no meaningful JS signer exists for the business API
Action:
- treat the verifier output as the real dynamic parameter
- solve and replay the verifier in protocol form
- do not simulate clicks in the final solution
Pattern J: Response data is encoded, compressed, or split
Symptoms:
- HTTP status is normal but payload looks like gibberish, digit soup, escaped code, glyphs, or binary
- business data only appears after a decode helper, font map, protobuf parser, or compression layer
- the response body shape changes after a local decode step, not after another request
Action:
- freeze the raw payload first
- trace the first consumer of the raw payload
- identify decode order, keys, maps, or parsers
- rebuild the decoder locally
- validate local decode on the exact captured payload before scaling
Pattern K: Transport is GraphQL, WebSocket, or a binary envelope
Symptoms:
- the URL stays stable but
operationName, frame type, or binary opcode changes
- request bodies carry nested
variables, message IDs, or channel names
- the real contract is in the envelope structure, not just one visible param
Action:
- document the transport kind explicitly
- freeze one known-good message or body sample
- separate envelope fields from business fields
- identify which fields are signed, sequenced, or server-assigned
- replay one stable message locally before attempting full stream collection
Pattern L: Public page still hides a bootstrap envelope
Symptoms:
- the page or homepage is publicly visible
- one early endpoint returns a public key, config blob, nonce seed, or short string instead of business data
- the real business request posts a wrapper such as
{"param":"..."} rather than the visible form fields
- compact JSON, a digest, a timestamp, and encryption or encoding are applied in a specific order
- list APIs work, but detail or submit APIs may still be permission-gated
Action:
- hit the real entry route once and capture the cookies that scope the public session
- freeze one bootstrap response and one successful business request
- prove the envelope build order exactly: raw payload, compact serialization, sign input, timestamp or nonce injection, final wrapper object, encryption or encoding, and outer transport field name
- verify long-message chunking rules when RSA or similar block ciphers wrap the payload
- make category, mode, and page parameters explicit instead of trusting UI defaults or empty values
- document list access and detail access separately so a public list is not mistaken for full public data access
Pattern M: Stateful WebSocket session with encrypted business frames
Symptoms:
- the target stays mostly idle until login, pairing, or a short warm-up exchange completes
- one or more early messages carry a ref, public key, client ID, secret seed, or challenge blob
- later frames are binary or protobuf and stay unreadable until session keys or counters are derived
- the stream dies unless auth, ack, heartbeat, reconnect, or message-tag rules are preserved
- media metadata is visible, but media download or decryption needs separate derivation from message payloads
Action:
- freeze one full successful transcript: bootstrap, login or pairing, auth ack, heartbeat, and one business frame
- separate frame families before reading payload semantics: bootstrap, auth, keepalive, business, receipt, media
- recover the exact key schedule or session-secret update path before blaming protobuf or compression
- document message tags, counters, and replay boundaries explicitly
- prove one stable local session first, then add stream collection, reconnect, or media handling
Tool Priorities
Every fresh target without upstream evidence must start with a startup gate, then an ordinary-Chrome-first analysis pass. Evidence-reuse tasks start from the provided artifacts and skip browser baseline unless the artifacts are insufficient:
- run
scripts/check_reverse_env.py when local execution is available, then classify the target with references/startup-triage-playbook.md
- use normal Chrome through
chrome-devtools-mcp for the first lightweight pass: page state, redirects, visible flow, and one first-pass network view
- use
js-reverse-mcp (normal Chrome) for initiator stacks, source search, wrapper tracing, breakpoints, and mutation hypotheses after the normal-Chrome baseline is captured
- escalate to CloakBrowser by calling
launch_browser({cloakBinaryPath: "D:\\..."})—this closes the normal browser and relaunches with CloakBrowser at the next tool call—only after fingerprint, anti-bot, or environment-verification evidence appears
Do not skip the normal-Chrome baseline on a fresh target without upstream evidence unless a real external blocker makes it unavailable, and if blocked, report that blocker explicitly.
CloakBrowser escalation is allowed only after one or more of these signs appear:
- normal Chrome receives fingerprint, webdriver, bot, risk-control,
403, 412, 429, or challenge behavior that a direct request or header diff cannot explain
- page code reads or hashes
navigator, screen, canvas, WebGL, audio, fonts, timing, plugins, permissions, WebRTC, or automation flags before the protected request
- clean normal-Chrome baseline and local replay disagree on fixed environment-dependent outputs
- hooks or breakpoints change the failure mode and you need a less detectable capture to separate observer effect from protocol logic
When CloakBrowser is used, record what evidence triggered the upgrade and keep the final collector browser-free. Use trace_property_access to capture exactly which environment properties the target page reads; use compare_env for one-shot environment snapshot comparisons.
Tool routing:
chrome-devtools-mcp: first browser baseline, page flow, UI-triggered requests
js-reverse-mcp: all ordinary JS reverse work (starts as normal Chrome; invoke launch_browser({cloakBinaryPath: "..."}) to switch to CloakBrowser at runtime)
Priority order:
- startup triage and least-destructive first move
chrome-devtools reconnaissance and network capture
js-reverse-mcp source search, wrapper tracing, and helper extraction
- request diffing
- helper verification on fixed inputs
- offline execution of extracted logic
- local protocol replay
Use deeper browser interaction only when one of these is true:
- a redirect chain or wrapper page must be observed once
- anti-debug defenses force offline extraction first
- a fixed input/output pair must be sampled from a page helper
The lightweight paired pass above is still mandatory on fresh targets. Even when deeper interaction is needed, the final collector must not depend on that browser step.
Bundled Scripts
Use local helper scripts when they shorten repeatable work:
scripts/scaffold_reverse_project.py: generate a protocol-first Python project skeleton with profile-aware layouts for generic, public-envelope, structured-transport, and response-decode targets
scripts/check_reverse_env.py: verify the minimal local reverse environment fast
scripts/crypto_fingerprint.py: fingerprint suspicious digest, Base64, or custom-alphabet outputs
scripts/protocol_diff.py: compare captured request or response samples and surface the meaningful deltas
For stateful stream targets, start from the structured-transport scaffold and split handshake, session, frame-codec, decode, and media logic into separate modules early.
Special routing:
- read
references/startup-triage-playbook.md when the target is fresh or the symptom is still broad
- read
references/workflow-overview.md when the task is still broad and you need the shortest end-to-end map
- read
references/cookie-provenance-playbook.md when a rotating cookie matters but its writer is still unclear
- read
references/hook-techniques.md before turning runtime validation into breakpoint chaos
- read
references/crypto-patterns.md before trusting helpers named after standard algorithms
- read
references/obfuscation-guide.md when packed bundles threaten to waste time
- read
references/anti-debug-playbook.md when live inspection becomes unstable
- read
references/environment-patch-playbook.md when local helper outputs diverge from live outputs
- read
references/jsvmp-analysis-playbook.md when a VM or bytecode interpreter hides the logic
- read
references/stateful-stream-e2ee-playbook.md when login or pairing bootstrap, session keys, heartbeats, binary frames, or media derivation are part of the contract
- read
references/troubleshooting-playbook.md when replay is close but still flaky
Reproduction Decision Tree
Choose delivery in this order:
- pure Python if all logic is restored
- Python plus minimal JS helper if the signer is exact in JS and porting now would add risk
- Python plus local WASM helper if the request param comes from a tiny export
- Python plus local bootstrap executor if the server returns JS that seeds cookies or tokens
- stop and keep reversing if the only remaining path is browser automation
Never choose:
- browser-backed replay as final delivery
- "works only in my browser profile" as acceptable handoff
- page-driving submission as the answer when protocol submission exists
Implementation Rules
- keep headers, cookies, signer logic, pagination, output, retries, and persistence in separate modules
- keep handshake bootstrap, session secrets, frame codecs, business parsing, and media derivation in separate modules when the target is stateful
- make
sessionid, timeout, retry, sleep, and output path explicit arguments
- log or print sign inputs and outputs until they match verified samples
- include fixed-input self-checks before live traffic
- capture one clean baseline before broad hooks on verifier-gated or behavior-sensitive targets
- prefer Python reimplementation of crypto before falling back to JS execution
- if JS is kept, keep it narrowly scoped to parameter restoration, signer logic, token generation, cookie reconstruction, or local decoding only
- make the final runtime split explicit: Python owns HTTP, pagination, retries, parsing, storage, and orchestration; JS owns only the minimal parameter restoration that still cannot be ported safely
- strip browser-only assumptions from helper code or emulate them locally without launching a browser
- prefer stdlib HTTP clients when you want zero dependencies or the environment's third-party stack is noisy
- preserve weird delimiters and non-ASCII separators explicitly
- treat bootstrap artifacts such as public keys, config blobs, nonce seeds, and wrapper field names as first-class inputs
- prove cookie provenance before caching or persisting rotating cookies in the collector
- validate compact JSON shape, sign input order, timestamp precision, and chunked-encryption boundaries separately before blaming the runtime
- save raw request and response samples during early development
- save all dynamic reconnaissance materials under the generated project's
js_reverse_cache/; keep final protocol code in that same scaffolded project directory under collector/ and curated notes under analysis/
- save one raw handshake transcript and one post-auth business frame before rewriting the collector
- support narrow per-page or per-request exceptions in configuration instead of hardcoding chaos into the main loop
- make category and pagination fields explicit when the page may be injecting hidden tab state
- fail loudly on unexpected response shapes
- if older notes disagree with live output, trust fresh live evidence
Verification Gates
Do not mark complete until all relevant gates pass:
- startup gate completed and updated if the target classification changed
- request path confirmed
- moving parts classified
- target family classified and initial routing recorded
- canonical mutation point identified
- first-pass
chrome-devtools evidence captured for fresh targets, or evidence-reuse path documented
- first-pass
js-reverse-mcp evidence captured for fresh targets, or evidence-reuse path documented
- relevant MCP capabilities considered through
references/tool-playbook.md before declaring a tooling blocker
- clean baseline captured before invasive tooling when the target is verifier-gated or behavior-sensitive
- normal-Chrome baseline captured before any CloakBrowser escalation on fresh targets without upstream evidence, unless normal Chrome was unavailable and that blocker is documented
- CloakBrowser use, if any, has explicit fingerprint, anti-bot, or environment-verification evidence and was done through
launch_browser({cloakBinaryPath: "..."}) on js-reverse-mcp
- helper outputs verified on fixed inputs
- structured transport rules documented when the target is not plain JSON
- response decode steps are local and repeatable when the payload is not directly readable
- fixed-sample checks exist for local decoders when decode is part of the contract
- bootstrap artifact replay confirmed when public routes still require key, config, cookie, or wrapper seeding
- cookie provenance proven when rotating cookies gate replay
- login or pairing bootstrap replay confirmed when the target needs a warm session before business traffic
- key schedule or session-secret derivation verified on captured samples when the stream is encrypted
- heartbeat, ack, counter, or message-tag rules documented when the stream is stateful
- raw frame parsing and business decode proven on at least one exact captured frame
- media-key derivation documented when file download or decryption uses separate secrets
- live replay succeeds repeatedly
- pagination or cursor advance confirmed
- account-bound constraints documented
- list-versus-detail permission boundaries documented when access levels differ
- page-specific exceptions documented
- final Python collector runs without browser automation or browser profiles
- final JS helper, if any, runs locally without browser automation or DOM dependence
- output saved in the requested format
Output Contract
After each meaningful phase, emit short structured reporting instead of vague prose.
Always return:
- which target family won the startup triage and why
- what
chrome-devtools proved about the site flow
- what
js-reverse-mcp proved about the mutation logic
- what the real endpoint is
- what the real moving parts are
- whether observer-effect risk showed up and how it was controlled
- whether CloakBrowser was used, and what evidence justified escalating beyond normal Chrome
- what the cookie provenance is when cookies mattered
- what was misleading
- what was verified with fixed inputs
- what the final protocol path is
- how the Python collector and JS helper are split
- confirmation that the final runtime is fully browser-free
- where the collector and sample output were saved
- what still looks unstable, if anything
Use the headings from references/report-templates.md when possible.
Skill Validation
When modifying this skill itself, validate against the official self-test suite before calling the edit complete.
Pass conditions:
- the route stays protocol-first
- every fresh target without upstream evidence begins with a normal-Chrome baseline before any CloakBrowser escalation
- CloakBrowser is used only after fingerprint, anti-bot, or environment-verification evidence is recorded
- final delivery never depends on browser automation
- final delivery is Python collector first, with JS limited to local parameter restoration only
- minimal missing evidence is requested instead of broad homework for the user
- the chosen references match the real symptom instead of generic cargo-cult loading
- output reports the real endpoint, real moving parts, and proof artifacts
- structured transport, decode chains, stateful sessions, and delivery gates are handled correctly when present
Anti-Patterns
- Do not ask the user to manually inspect giant bundles if tooling can inspect them.
- Do not skip
chrome-devtools-mcp or js-reverse-mcp on a fresh target unless you report a real blocker.
- Do not launch CloakBrowser as the first move for ordinary JS reverse tasks.
- Do not jump straight to Selenium or Playwright when a direct API exists.
- Do not install broad hooks before capturing a clean baseline on verifier-gated or behavior-sensitive targets.
- Do not confuse business-layer params with wire-layer params.
- Do not trust helper names without fixed-input proof.
- Do not call browser-only behavior before checking page-specific headers or cookies.
- Do not hardcode rotating cookies before proving who writes them and how they refresh.
- Do not bury every concern in one
main.py.
- Do not stop after one lucky success.
- Do not ship a browser automation script when the task is protocol-recoverable.
- Do not hide automation behind words like "temporary collector" or "reliable fallback".
- Do not leave final JS helpers coupled to
window, document, browser storage, or manual browser state when they can be made local and deterministic.
Reference Router
Read focused generic references when the symptom matches:
references/startup-triage-playbook.md when the target is fresh and the first question is "what kind of fight is this?"
references/workflow-overview.md for the shortest end-to-end execution map
references/tool-playbook.md for tool choice and next-step routing
references/report-templates.md for phase reporting and handoff structure
references/official-self-test-task-suite.md when validating whether the skill still generalizes after edits
references/cookie-provenance-playbook.md when a cookie is blocking replay but the writer or refresh path is still unclear
references/crypto-patterns.md when signatures or helper outputs look suspicious
references/obfuscation-guide.md when packed code or string tables dominate the bundle
references/hook-techniques.md when runtime proof is faster than static reading
references/anti-debug-playbook.md when the page destabilizes tooling
references/environment-patch-playbook.md when local execution diverges from live execution
references/env-diff-playbook.md when redirects, wrappers, or environment-specific behavior cause mismatches
references/jsvmp-analysis-playbook.md when a custom VM or bytecode interpreter hides the logic
references/structured-transport-playbook.md when GraphQL, WebSocket, protobuf, msgpack, or binary envelopes carry the real contract
references/stateful-stream-e2ee-playbook.md when login, pairing, session keys, keepalive frames, or media decryption make the stream stateful
references/response-decode-playbook.md when the payload needs local decode before it becomes usable data
references/public-bootstrap-envelope-playbook.md when a public page still needs bootstrap keys, cookies, config, or an encrypted wrapper before list replay works
references/delivery-gate-playbook.md when you need to decide
…(truncated)
1---2name: web-protocol-recovery3description: Reverse hostile web clients into pure-protocol Python collectors. Use when the goal is end-to-end browser-free protocol recovery: sign/cookie/challenge/bootstrap/WASM/font decode/transport wrapper/WebSocket/GraphQL/protobuf/response decode, or when upstream evidence already includes real requests, call stacks, signer formulas, fixed input-output samples, or response samples and the user asks to implement replay code. Do not trigger for single-point work: only locate sign/token/header entry (camoufox-js-reverse), only generate browser hook snippets (browser-hook-snippets), Node.js/vm environment patching (env-patch), AST deobfuscation (ast-deobfuscate), compact Python+iv8 scripts (iv8-web-reverse), or WeChat miniapp runtime debugging (wechat-miniapp-reverse).4---56# Web Protocol Recovery78## Role910Turn hostile web clients into stable protocol collectors.1112This skill is not a browser automation skill.13This skill is a protocol recovery skill.1415Default posture:16171. start every fresh target without upstream evidence with an ordinary Chrome baseline before any CloakBrowser escalation182. find the real request193. identify the true changing state204. rebuild that state offline215. deliver a browser-free Python collector, plus a local JS parameter helper only when truly needed2223## Trigger Boundary2425Use this skill when the user wants a complete browser-free collector or protocol replay, not merely one missing component.2627Trigger when:2829- the task asks to build, repair, or stabilize a crawler/collector/replay script outside the browser30- several moving parts must be recovered together, such as signature + bootstrap cookie + response decode + transport wrapper31- the target is WebSocket, GraphQL, protobuf, msgpack, encrypted response, dynamic-font decode, or stateful session protocol32- another skill or the user already supplied real request samples, call stacks, signer formulas, fixed input-output samples, or response bodies and now asks for implementation3334Do not trigger when:3536- only the sign/token/header entry, script URL, function name, or call stack is unknown -> `camoufox-js-reverse`37- only a Console/Snippets hook script is requested -> `browser-hook-snippets`38- a known browser JS entry must be made to run in Node.js/vm/jsdom -> `env-patch`39- the request is a compact Python + iv8 + requests script -> `iv8-web-reverse`40- the task is whole-file AST deobfuscation or control-flow restoration -> `ast-deobfuscate`41- the target is WeChat miniapp / WMPF runtime debugging -> `wechat-miniapp-reverse`4243## Non-Negotiables4445- Final delivery must be pure protocol: raw HTTP plus local signer, local decoder, or local bootstrap helper only.46- Every fresh target without upstream evidence must get a normal-Chrome baseline before writing the final collector.47- Use `js-reverse-mcp` (starts in normal Chrome) for all ordinary JS reverse work.48- To switch to CloakBrowser at runtime: call `launch_browser` with `cloakBinaryPath` pointing to the CloakBrowser binary.49- To switch back to normal Chrome: call `launch_browser` with an empty `cloakBinaryPath`.50- Do not start CloakBrowser for ordinary signer, wrapper, decode, or request-diff work.51- Do not ship Playwright, Selenium, CDP page-driving, or submit-through-browser flows as the solution.52- Final delivery must run fully outside the browser: Python crawler scripts for collection, plus a local JS helper only for parameter, sign, token, or cookie reconstruction when Python porting is not yet the safest choice.53- Prefer Python for the collector and orchestration.54- Only keep a tiny isolated JS or WASM helper when a verified Python port is not yet cheaper, safer, or faster to maintain.55- Any JS helper must run locally without page driving, `document`, `window`, manual clicks, browser profiles, or hidden browser dependencies.56- If browser tooling is used at all, use it only for recon and evidence gathering, never as a hidden dependency in the final collector.57- Automation is forbidden as the final answer, forbidden as a fallback answer, and forbidden as a disguised "temporary" delivery path.58- Recover one stable request before scaling pagination, concurrency, or submission.59- Every conclusion must be backed by artifacts: request samples, fixed-input helper outputs, cookies, headers, and replay proof.60- All reconnaissance artifacts such as downloaded JS, WASM, fonts, HTML, network exports, state snapshots, screenshots, traces, and fixed-input vectors must go under the generated project's root-level `js_reverse_cache/`; create the project scaffold before saving target artifacts.61- Final collector code must live in the same dedicated protocol project directory using the bundled scaffold shape: `analysis/`, `collector/`, `js_reverse_cache/`, `tests/`, `README.md`, and `requirements.txt`. Do not collapse the delivery into a single `main.py` except for a temporary throwaway probe saved under that project's `js_reverse_cache/`.62- Stay in one execution loop until you reach protocol delivery or hit a real external blocker.6364## Confirmation Checkpoints6566Do not let protocol recovery expand from artifact analysis into live side effects without a short user confirmation. Pause before:6768- using account-bound cookies, Authorization headers, session ids, private API keys, or paid/privileged data sources in live replay69- submitting verifier answers, CAPTCHA/behavior payloads, forms, mutations, orders, payments, messages, or any request that can change server state70- increasing from one stable proof request to pagination, concurrency, retries, long-running collection, or high-volume scraping71- saving or printing full raw cookies, tokens, Authorization values, request bodies, response bodies, decrypted payloads, or account-bound samples; default to minimal fields, hashes, lengths, or masked excerpts72- switching from evidence reuse to fresh browser reconnaissance because provided artifacts are insufficient; state the missing artifact first, then ask for permission to collect it7374No pause is needed for offline fixed-input signer checks, local decoder tests, static source reading, or replay against user-provided mock/sample artifacts.7576## Startup Gate7778Before any deep tool use on a fresh target, emit a short startup gate and fill it with current evidence.7980Evidence reuse path:8182- if the task arrives from another skill, or the user already supplied real requests, headers/cookies, call stacks, signer formulas, fixed input-output samples, or response bodies, do not redo browser availability checks just to satisfy the fresh-target gate83- for this path, confirm the artifact directory, classify the protocol family, declare the final collector shape, then implement and verify against the provided artifacts or live replay when allowed8485Required checks:86871. environment and tool sanity for fresh targets without upstream evidence88 - run `scripts/check_reverse_env.py` when local execution is available89 - confirm whether `chrome-devtools-mcp` and `js-reverse-mcp` (normal Chrome, switchable to CloakBrowser via `launch_browser`) are usable90 - record the browser tier: normal Chrome first, CloakBrowser only after explicit escalation evidence91 - if one tool is blocked, report the blocker before pretending the target is understood922. artifact directory discipline93 - confirm the generated protocol project root has `js_reverse_cache/`, or create/scaffold the project before saving dynamic materials94 - save browser/network/source/state artifacts under the project's `js_reverse_cache/`, and save final collector code under the same dedicated protocol project directory953. family triage96 - classify the target first as `signer-gated`, `verifier-gated`, `decode-gated`, or `session-gated`97 - read `references/startup-triage-playbook.md` before loading giant bundles98 - if a rotating cookie appears important, read `references/cookie-provenance-playbook.md` before hardcoding anything994. delivery intent100 - state the intended final shape: pure Python, Python plus tiny JS helper, Python plus tiny WASM helper, or Python plus local bootstrap executor101 - explicitly reject browser-backed fetches, browser profiles, and automation-driven replay as the final answer102103Rule:104105- if the startup gate is incomplete, the target is not yet understood106- if the classification changes after new evidence, restate the gate instead of silently drifting107108## What This Skill Optimizes For109110- protocol-first reverse engineering111- Python-first delivery112- offline reproduction of dynamic state113- reusable collectors instead of one-off lucky requests114- generic methodology that transfers across similar targets115116## Reference Layout117118The `references/` directory is organized by purpose:119120- root-level playbooks are generic pattern documents and reusable workflows121122Rule:123124- read generic pattern playbooks first125- abstract solved work back into generic patterns instead of storing site-specific folklore126127## Similarity Heuristics128129Treat a target as belonging to the same family when one or more of these symptoms appear:130131- page code mentions one endpoint but the wire uses another132- business code builds `token`, `sign`, or `m`, but transport wrappers rewrite it before send133- the transport is GraphQL, WebSocket frames, protobuf, msgpack, or another structured envelope rather than plain JSON134- standard helper names such as `md5`, `btoa`, `atob`, or `sha1` produce nonstandard output135- the first request returns JavaScript, cookies, offsets, or font files instead of business data136- the page is public, but a bootstrap endpoint still returns a public key, config blob, nonce seed, or wrapper contract before list requests work137- only one page fails, often the last page138- the page text says login or `sessionid` matters, and the answer differs per account139- the site ships a tiny side script or `.wasm` that looks unrelated but actually seeds signing state140- the API returns strings, hints, glyphs, or fonts instead of the final numeric payload141- the response body is encoded, compressed, protobuf, msgpack, or split across multiple layers before it becomes usable data142- the same request succeeds once and then dies unless some hidden refresh state is regenerated143- list APIs work anonymously, but detail or submit APIs still reject without a different permission boundary144- empty filter values do not reproduce the visible tab because the page injects category or mode state before send145- a login or pairing step returns a ref, QR seed, public key, or client identifier before business frames become readable146- the target keeps one long-lived WebSocket alive with auth, ack, heartbeat, or reconnect frames that must stay in order147- media metadata arrives in one place, but the actual file replay or decryption needs a separately derived key148149If the symptoms match, reuse the methodology even when the exact site and parameter names differ.150151## Operating Doctrine152153### Doctrine 1: Trust the wire, not the page text154155- Real request paths beat page hints.156- Real headers beat visible business code.157- Real cookies beat guessed token stories.158- Real response shape beats archived notes.159160### Doctrine 2: The dynamic parameter is not always a signature161162The real moving part may be:163164- a cookie165- a page-specific header166- a transport envelope167- a server-returned JS bootstrap168- a dynamic font169- a WebAssembly export170- a transport wrapper rewrite171- a response-side decoder172- an account-bound session contract173174Do not assume every hard target is solved by hunting a `sign` function.175176### Doctrine 3: Fixed-input validation beats naming177178If a page helper is called `md5` or `btoa`, prove it on fixed inputs before trusting the name.179180Minimum standard for suspicious helpers:1811821. pick a fixed input such as `"abc"` or a captured timestamp1832. record browser output1843. record local output1854. compare intermediate values, not just final output186187### Doctrine 4: Narrow exceptions stay narrow188189If only one page needs a special `User-Agent`, or only one request needs a rotated cookie, encode that exception explicitly.190Do not poison the entire collector with a fake "browser-only" conclusion.191192### Doctrine 5: Automation is not an acceptable crutch193194When stuck, do more protocol work:195196- diff requests197- extract inline scripts198- run bootstrap JS locally199- port helper logic200- instantiate WASM locally201- decode fonts locally202203Do not fall back to browser automation as delivery.204205### Doctrine 6: Environment mismatch is evidence206207When local output and live output disagree, treat the mismatch as evidence:208209- compare fixed inputs210- compare side assets211- compare patched helpers212- compare environment branches213214Do not hand-wave the mismatch away as "probably browser-only".215216### Doctrine 7: Delivery gates outrank convenience217218If the only known path still depends on live page context, the task is not done.219220- a browser profile is not a protocol artifact221- a hidden refresh click is not a collector222- an unexplained decoder is not acceptable handoff223224Keep reversing until the moving parts are local, explicit, and testable.225226### Doctrine 8: Public does not mean unsigned227228Anonymous pages still have protocol contracts.229230- a public list may still require entry-route cookies231- a bootstrap endpoint may still return the key, config, or envelope seed232- list visibility does not prove detail or submit visibility233234Treat anonymous access, envelope construction, and permission boundaries as separate questions.235236### Doctrine 9: Stateful streams are protocol, not browser magic237238If the target only becomes readable after login, pairing, or a warm-up WebSocket exchange, the session transcript is part of the protocol.239240- pairing or login bootstrap is not UI fluff241- handshake outputs are protocol artifacts242- heartbeats, ack frames, counters, and reconnect rules are part of the collector243244Do not collapse a stateful stream problem into a fake single-request sign story.245246### Doctrine 10: Observer effect is real247248Some targets get harder after you touch them.249250- verifier-gated or behavior-sensitive flows may change once hooks, breakpoints, or monkey patches are installed251- capture one clean baseline request and response before invasive instrumentation252- prefer initiator stacks, request diffs, and narrow boundary hooks before broad global hooks253- if hooking changes the failure mode, treat that as evidence that your tooling is perturbing the target254255Do not confuse hook-induced breakage with proof that the site is "browser-only".256257### Doctrine 11: Cookie provenance beats cookie superstition258259When a cookie gates replay, prove where it came from:260261- `Set-Cookie` on a protocol response262- `document.cookie` from page code263- server-returned challenge or bootstrap JS264- redirect wrappers, iframes, workers, or SDK side effects265- a derived header or token that only looks like a cookie problem266267Do not hardcode a rotating business cookie before proving its writer and refresh path.268269## Minimal Intake270271Start immediately if the user already provided enough evidence.272273Otherwise ask only for the smallest missing set:274275- target page URL, or276- target API URL, or277- site homepage plus collection goal, or278- captured request sample, or279- JS snippet, obfuscated bundle, cookie sample, sign sample, or packet capture280281Only ask follow-ups that change implementation:282283- target fields284- scope: single page, pagination, category, date range, or whole site285- output format: JSON, CSV, Excel, database, or API sink286- whether login is required287- whether incremental sync, dedupe, or resume is required288289## Universal Reverse Loop290291### Phase 0: Fingerprint before deep work292293Classify the target before reading giant bundles:294295- decoy endpoint vs real endpoint296- wrapper rewrite vs visible param297- patched helper vs standard helper298- signer-gated vs verifier-gated vs decode-gated vs session-gated299- bootstrap asset vs direct data API300- plain JSON vs GraphQL vs WebSocket vs binary envelope301- single-shot replay vs stateful session with pairing, auth, or warm-up frames302- direct response vs encoded response vs glyph-mapped response303- page-specific exception vs whole-flow exception304- session-bound vs anonymous305- clean-baseline-first vs trace-first vs decode-first vs transcript-first306- rotating-cookie provenance known vs unknown307- JSVMP or heavy obfuscation vs normal packed bundle308309Browser tier rule:310311- `js-reverse-mcp` starts in normal Chrome; it is the default for all ordinary JS reverse work312- CloakBrowser is activated at runtime via `launch_browser({cloakBinaryPath: "..."})`—no separate MCP server needed313- when no fingerprint evidence exists, use `js-reverse-mcp` in normal-Chrome mode for everything314315Goal:316317- choose the smallest next proof and the least destructive first instrument, not the biggest code dump318319### Phase 1: Identify the true request path320321- follow redirects322- inspect wrapper pages and compatibility pages323- separate visible page routes from real wire routes324- map bootstrap requests, list requests, detail requests, submission requests, and risk-control requests325- detect whether one endpoint serves both bootstrap and final data in separate phases326327Deliverable for this phase:328329- one confirmed request that is definitely on the real business path330331### Phase 2: Classify the moving parts332333For the real request, classify each changing field:334335- static header336- rotating header337- static cookie338- rotating cookie339- timestamp340- nonce or random fragment341- signed body or query342- transport envelope, operation name, or message type343- compressed or binary response format344- decode key, glyph map, or response-side transform345- encrypted response346- page-specific exception347- account-bound session dependency348- bootstrap artifact dependency349- login or pairing bootstrap artifact350- session key schedule or exported secret material351- heartbeat, ack, counter, or message-tag state352- media-key derivation or side-channel download secret353354Goal:355356- separate what must be reproduced from what is just noise357358### Phase 3: Locate the canonical mutation point359360Look in this order:3613621. transport wrappers such as `$.ajaxSetup`, `beforeSend`, fetch wrappers, interceptors3632. bootstrap side scripts and inline payloads3643. page-exposed helper functions3654. WebAssembly exports3665. server-returned JS challenges3676. response-side refresh fields that seed the next request3687. handshake transcripts, frame serializers, binary node encoders, protobuf parsers, or session key schedules369370Rule:371372- the canonical mutation point is where the wire payload actually changes, not where the business code first creates a placeholder373374### Phase 4: Rebuild the moving parts offline375376Choose the cheapest valid offline shape:3773781. pure Python3792. Python plus isolated JS signer3803. Python plus minimal local JS or WASM helper3814. Python plus local challenge bootstrap executor3825. Python plus local font decoder383384Never add browser automation to the final path.385386### Phase 5: Prove repeatability387388Do not call it solved until:389390- the same logic succeeds at least 2 to 3 times391- pagination advances correctly392- final fields are complete393- dynamic state regenerates correctly394- account-bound constraints are documented395396## Pattern Atlas397398### Pattern A: The endpoint on the page is fake399400Symptoms:401402- page code hooks `/api/match/...`403- wire uses `/api/question/...` or another path404- browser request succeeds but replaying the visible path fails405406Action:407408- trust the network path409- trace request initiators410- document the decoy path411- code against the live path only412413### Pattern B: The business param is a decoy414415Symptoms:416417- page code builds `token`418- wire sends `m`, `f`, or another field419- request wrapper mutates data before send420421Action:422423- reverse the wrapper first424- diff business-layer params against final payload425- rebuild the wrapper logic, not the decoy field426427### Pattern C: Standard helper is patched428429Symptoms:430431- `md5`, `btoa`, `atob`, `sha1`, or similar names exist432- local reproduction with standard libraries does not match browser output433434Action:435436- freeze fixed test vectors437- port the exact helper implementation438- verify helper outputs before using them in requests439440### Pattern D: First response is not data, but bootstrap441442Symptoms:443444- first request returns JS, `Set-Cookie`, offset scripts, or challenge tokens445- replay works only after the bootstrap response is processed446447Action:448449- treat bootstrap as part of the protocol contract450- execute or emulate it locally451- carry resulting cookies or globals into the next request452453### Pattern E: Only one page breaks454455Symptoms:456457- pages 1 to 4 work458- page 5 fails or returns hints, strings, or anti-bot signals459460Action:461462- diff headers and cookies by page463- test page-specific `User-Agent`, referer, or ordering rules464- encode the exception narrowly465466### Pattern F: Answer or data is account-bound467468Symptoms:469470- page text mentions `sessionid`471- different accounts produce different sums or answers472- submit works only with the same session that collected the data473474Action:475476- make `sessionid` explicit in the collector477- keep fetch and submit under the same account478- verify with the same session before blaming signer logic479480### Pattern G: Tiny side assets carry the whole signer481482Symptoms:483484- `.wasm`, `/offset`, challenge JS, or font files appear trivial485- main bundle is noisy but side asset changes output decisively486487Action:488489- inspect side assets early490- instantiate WASM locally491- execute bootstrap JS locally492- decode fonts locally493494### Pattern H: Dynamic fonts hide the payload495496Symptoms:497498- numeric values appear as glyphs or meaningless text499- response includes font URLs or embedded font data500501Action:502503- fetch the font asset504- derive the codepoint-to-digit map505- decode the payload locally506507### Pattern I: One-shot verifier, captcha, or click challenge508509Symptoms:510511- next request only works after a verification step512- no meaningful JS signer exists for the business API513514Action:515516- treat the verifier output as the real dynamic parameter517- solve and replay the verifier in protocol form518- do not simulate clicks in the final solution519520### Pattern J: Response data is encoded, compressed, or split521522Symptoms:523524- HTTP status is normal but payload looks like gibberish, digit soup, escaped code, glyphs, or binary525- business data only appears after a decode helper, font map, protobuf parser, or compression layer526- the response body shape changes after a local decode step, not after another request527528Action:529530- freeze the raw payload first531- trace the first consumer of the raw payload532- identify decode order, keys, maps, or parsers533- rebuild the decoder locally534- validate local decode on the exact captured payload before scaling535536### Pattern K: Transport is GraphQL, WebSocket, or a binary envelope537538Symptoms:539540- the URL stays stable but `operationName`, frame type, or binary opcode changes541- request bodies carry nested `variables`, message IDs, or channel names542- the real contract is in the envelope structure, not just one visible param543544Action:545546- document the transport kind explicitly547- freeze one known-good message or body sample548- separate envelope fields from business fields549- identify which fields are signed, sequenced, or server-assigned550- replay one stable message locally before attempting full stream collection551552### Pattern L: Public page still hides a bootstrap envelope553554Symptoms:555556- the page or homepage is publicly visible557- one early endpoint returns a public key, config blob, nonce seed, or short string instead of business data558- the real business request posts a wrapper such as `{"param":"..."}` rather than the visible form fields559- compact JSON, a digest, a timestamp, and encryption or encoding are applied in a specific order560- list APIs work, but detail or submit APIs may still be permission-gated561562Action:563564- hit the real entry route once and capture the cookies that scope the public session565- freeze one bootstrap response and one successful business request566- prove the envelope build order exactly: raw payload, compact serialization, sign input, timestamp or nonce injection, final wrapper object, encryption or encoding, and outer transport field name567- verify long-message chunking rules when RSA or similar block ciphers wrap the payload568- make category, mode, and page parameters explicit instead of trusting UI defaults or empty values569- document list access and detail access separately so a public list is not mistaken for full public data access570571### Pattern M: Stateful WebSocket session with encrypted business frames572573Symptoms:574575- the target stays mostly idle until login, pairing, or a short warm-up exchange completes576- one or more early messages carry a ref, public key, client ID, secret seed, or challenge blob577- later frames are binary or protobuf and stay unreadable until session keys or counters are derived578- the stream dies unless auth, ack, heartbeat, reconnect, or message-tag rules are preserved579- media metadata is visible, but media download or decryption needs separate derivation from message payloads580581Action:582583- freeze one full successful transcript: bootstrap, login or pairing, auth ack, heartbeat, and one business frame584- separate frame families before reading payload semantics: bootstrap, auth, keepalive, business, receipt, media585- recover the exact key schedule or session-secret update path before blaming protobuf or compression586- document message tags, counters, and replay boundaries explicitly587- prove one stable local session first, then add stream collection, reconnect, or media handling588589## Tool Priorities590591Every fresh target without upstream evidence must start with a startup gate, then an ordinary-Chrome-first analysis pass. Evidence-reuse tasks start from the provided artifacts and skip browser baseline unless the artifacts are insufficient:5925931. run `scripts/check_reverse_env.py` when local execution is available, then classify the target with `references/startup-triage-playbook.md`5942. use normal Chrome through `chrome-devtools-mcp` for the first lightweight pass: page state, redirects, visible flow, and one first-pass network view5953. use `js-reverse-mcp` (normal Chrome) for initiator stacks, source search, wrapper tracing, breakpoints, and mutation hypotheses after the normal-Chrome baseline is captured5964. escalate to CloakBrowser by calling `launch_browser({cloakBinaryPath: "D:\\..."})`—this closes the normal browser and relaunches with CloakBrowser at the next tool call—only after fingerprint, anti-bot, or environment-verification evidence appears597598Do not skip the normal-Chrome baseline on a fresh target without upstream evidence unless a real external blocker makes it unavailable, and if blocked, report that blocker explicitly.599600CloakBrowser escalation is allowed only after one or more of these signs appear:601602- normal Chrome receives fingerprint, webdriver, bot, risk-control, `403`, `412`, `429`, or challenge behavior that a direct request or header diff cannot explain603- page code reads or hashes `navigator`, `screen`, canvas, WebGL, audio, fonts, timing, plugins, permissions, WebRTC, or automation flags before the protected request604- clean normal-Chrome baseline and local replay disagree on fixed environment-dependent outputs605- hooks or breakpoints change the failure mode and you need a less detectable capture to separate observer effect from protocol logic606607When CloakBrowser is used, record what evidence triggered the upgrade and keep the final collector browser-free. Use `trace_property_access` to capture exactly which environment properties the target page reads; use `compare_env` for one-shot environment snapshot comparisons.608609Tool routing:610611- `chrome-devtools-mcp`: first browser baseline, page flow, UI-triggered requests612- `js-reverse-mcp`: all ordinary JS reverse work (starts as normal Chrome; invoke `launch_browser({cloakBinaryPath: "..."})` to switch to CloakBrowser at runtime)613614Priority order:6156161. startup triage and least-destructive first move6172. `chrome-devtools` reconnaissance and network capture6183. `js-reverse-mcp` source search, wrapper tracing, and helper extraction6194. request diffing6205. helper verification on fixed inputs6216. offline execution of extracted logic6227. local protocol replay623624Use deeper browser interaction only when one of these is true:625626- a redirect chain or wrapper page must be observed once627- anti-debug defenses force offline extraction first628- a fixed input/output pair must be sampled from a page helper629630The lightweight paired pass above is still mandatory on fresh targets. Even when deeper interaction is needed, the final collector must not depend on that browser step.631632## Bundled Scripts633634Use local helper scripts when they shorten repeatable work:635636- `scripts/scaffold_reverse_project.py`: generate a protocol-first Python project skeleton with profile-aware layouts for `generic`, `public-envelope`, `structured-transport`, and `response-decode` targets637- `scripts/check_reverse_env.py`: verify the minimal local reverse environment fast638- `scripts/crypto_fingerprint.py`: fingerprint suspicious digest, Base64, or custom-alphabet outputs639- `scripts/protocol_diff.py`: compare captured request or response samples and surface the meaningful deltas640641For stateful stream targets, start from the `structured-transport` scaffold and split handshake, session, frame-codec, decode, and media logic into separate modules early.642643Special routing:644645- read `references/startup-triage-playbook.md` when the target is fresh or the symptom is still broad646- read `references/workflow-overview.md` when the task is still broad and you need the shortest end-to-end map647- read `references/cookie-provenance-playbook.md` when a rotating cookie matters but its writer is still unclear648- read `references/hook-techniques.md` before turning runtime validation into breakpoint chaos649- read `references/crypto-patterns.md` before trusting helpers named after standard algorithms650- read `references/obfuscation-guide.md` when packed bundles threaten to waste time651- read `references/anti-debug-playbook.md` when live inspection becomes unstable652- read `references/environment-patch-playbook.md` when local helper outputs diverge from live outputs653- read `references/jsvmp-analysis-playbook.md` when a VM or bytecode interpreter hides the logic654- read `references/stateful-stream-e2ee-playbook.md` when login or pairing bootstrap, session keys, heartbeats, binary frames, or media derivation are part of the contract655- read `references/troubleshooting-playbook.md` when replay is close but still flaky656657## Reproduction Decision Tree658659Choose delivery in this order:6606611. pure Python if all logic is restored6622. Python plus minimal JS helper if the signer is exact in JS and porting now would add risk6633. Python plus local WASM helper if the request param comes from a tiny export6644. Python plus local bootstrap executor if the server returns JS that seeds cookies or tokens6655. stop and keep reversing if the only remaining path is browser automation666667Never choose:668669- browser-backed replay as final delivery670- "works only in my browser profile" as acceptable handoff671- page-driving submission as the answer when protocol submission exists672673## Implementation Rules674675- keep headers, cookies, signer logic, pagination, output, retries, and persistence in separate modules676- keep handshake bootstrap, session secrets, frame codecs, business parsing, and media derivation in separate modules when the target is stateful677- make `sessionid`, timeout, retry, sleep, and output path explicit arguments678- log or print sign inputs and outputs until they match verified samples679- include fixed-input self-checks before live traffic680- capture one clean baseline before broad hooks on verifier-gated or behavior-sensitive targets681- prefer Python reimplementation of crypto before falling back to JS execution682- if JS is kept, keep it narrowly scoped to parameter restoration, signer logic, token generation, cookie reconstruction, or local decoding only683- make the final runtime split explicit: Python owns HTTP, pagination, retries, parsing, storage, and orchestration; JS owns only the minimal parameter restoration that still cannot be ported safely684- strip browser-only assumptions from helper code or emulate them locally without launching a browser685- prefer stdlib HTTP clients when you want zero dependencies or the environment's third-party stack is noisy686- preserve weird delimiters and non-ASCII separators explicitly687- treat bootstrap artifacts such as public keys, config blobs, nonce seeds, and wrapper field names as first-class inputs688- prove cookie provenance before caching or persisting rotating cookies in the collector689- validate compact JSON shape, sign input order, timestamp precision, and chunked-encryption boundaries separately before blaming the runtime690- save raw request and response samples during early development691- save all dynamic reconnaissance materials under the generated project's `js_reverse_cache/`; keep final protocol code in that same scaffolded project directory under `collector/` and curated notes under `analysis/`692- save one raw handshake transcript and one post-auth business frame before rewriting the collector693- support narrow per-page or per-request exceptions in configuration instead of hardcoding chaos into the main loop694- make category and pagination fields explicit when the page may be injecting hidden tab state695- fail loudly on unexpected response shapes696- if older notes disagree with live output, trust fresh live evidence697698## Verification Gates699700Do not mark complete until all relevant gates pass:701702- startup gate completed and updated if the target classification changed703- request path confirmed704- moving parts classified705- target family classified and initial routing recorded706- canonical mutation point identified707- first-pass `chrome-devtools` evidence captured for fresh targets, or evidence-reuse path documented708- first-pass `js-reverse-mcp` evidence captured for fresh targets, or evidence-reuse path documented709- relevant MCP capabilities considered through `references/tool-playbook.md` before declaring a tooling blocker710- clean baseline captured before invasive tooling when the target is verifier-gated or behavior-sensitive711- normal-Chrome baseline captured before any CloakBrowser escalation on fresh targets without upstream evidence, unless normal Chrome was unavailable and that blocker is documented712- CloakBrowser use, if any, has explicit fingerprint, anti-bot, or environment-verification evidence and was done through `launch_browser({cloakBinaryPath: "..."})` on `js-reverse-mcp`713- helper outputs verified on fixed inputs714- structured transport rules documented when the target is not plain JSON715- response decode steps are local and repeatable when the payload is not directly readable716- fixed-sample checks exist for local decoders when decode is part of the contract717- bootstrap artifact replay confirmed when public routes still require key, config, cookie, or wrapper seeding718- cookie provenance proven when rotating cookies gate replay719- login or pairing bootstrap replay confirmed when the target needs a warm session before business traffic720- key schedule or session-secret derivation verified on captured samples when the stream is encrypted721- heartbeat, ack, counter, or message-tag rules documented when the stream is stateful722- raw frame parsing and business decode proven on at least one exact captured frame723- media-key derivation documented when file download or decryption uses separate secrets724- live replay succeeds repeatedly725- pagination or cursor advance confirmed726- account-bound constraints documented727- list-versus-detail permission boundaries documented when access levels differ728- page-specific exceptions documented729- final Python collector runs without browser automation or browser profiles730- final JS helper, if any, runs locally without browser automation or DOM dependence731- output saved in the requested format732733## Output Contract734735After each meaningful phase, emit short structured reporting instead of vague prose.736737Always return:738739- which target family won the startup triage and why740- what `chrome-devtools` proved about the site flow741- what `js-reverse-mcp` proved about the mutation logic742- what the real endpoint is743- what the real moving parts are744- whether observer-effect risk showed up and how it was controlled745- whether CloakBrowser was used, and what evidence justified escalating beyond normal Chrome746- what the cookie provenance is when cookies mattered747- what was misleading748- what was verified with fixed inputs749- what the final protocol path is750- how the Python collector and JS helper are split751- confirmation that the final runtime is fully browser-free752- where the collector and sample output were saved753- what still looks unstable, if anything754755Use the headings from `references/report-templates.md` when possible.756757## Skill Validation758759When modifying this skill itself, validate against the official self-test suite before calling the edit complete.760761Pass conditions:762763- the route stays protocol-first764- every fresh target without upstream evidence begins with a normal-Chrome baseline before any CloakBrowser escalation765- CloakBrowser is used only after fingerprint, anti-bot, or environment-verification evidence is recorded766- final delivery never depends on browser automation767- final delivery is Python collector first, with JS limited to local parameter restoration only768- minimal missing evidence is requested instead of broad homework for the user769- the chosen references match the real symptom instead of generic cargo-cult loading770- output reports the real endpoint, real moving parts, and proof artifacts771- structured transport, decode chains, stateful sessions, and delivery gates are handled correctly when present772773## Anti-Patterns774775- Do not ask the user to manually inspect giant bundles if tooling can inspect them.776- Do not skip `chrome-devtools-mcp` or `js-reverse-mcp` on a fresh target unless you report a real blocker.777- Do not launch CloakBrowser as the first move for ordinary JS reverse tasks.778- Do not jump straight to Selenium or Playwright when a direct API exists.779- Do not install broad hooks before capturing a clean baseline on verifier-gated or behavior-sensitive targets.780- Do not confuse business-layer params with wire-layer params.781- Do not trust helper names without fixed-input proof.782- Do not call browser-only behavior before checking page-specific headers or cookies.783- Do not hardcode rotating cookies before proving who writes them and how they refresh.784- Do not bury every concern in one `main.py`.785- Do not stop after one lucky success.786- Do not ship a browser automation script when the task is protocol-recoverable.787- Do not hide automation behind words like "temporary collector" or "reliable fallback".788- Do not leave final JS helpers coupled to `window`, `document`, browser storage, or manual browser state when they can be made local and deterministic.789790## Reference Router791792Read focused generic references when the symptom matches:793794- `references/startup-triage-playbook.md` when the target is fresh and the first question is "what kind of fight is this?"795- `references/workflow-overview.md` for the shortest end-to-end execution map796- `references/tool-playbook.md` for tool choice and next-step routing797- `references/report-templates.md` for phase reporting and handoff structure798- `references/official-self-test-task-suite.md` when validating whether the skill still generalizes after edits799- `references/cookie-provenance-playbook.md` when a cookie is blocking replay but the writer or refresh path is still unclear800- `references/crypto-patterns.md` when signatures or helper outputs look suspicious801- `references/obfuscation-guide.md` when packed code or string tables dominate the bundle802- `references/hook-techniques.md` when runtime proof is faster than static reading803- `references/anti-debug-playbook.md` when the page destabilizes tooling804- `references/environment-patch-playbook.md` when local execution diverges from live execution805- `references/env-diff-playbook.md` when redirects, wrappers, or environment-specific behavior cause mismatches806- `references/jsvmp-analysis-playbook.md` when a custom VM or bytecode interpreter hides the logic807- `references/structured-transport-playbook.md` when GraphQL, WebSocket, protobuf, msgpack, or binary envelopes carry the real contract808- `references/stateful-stream-e2ee-playbook.md` when login, pairing, session keys, keepalive frames, or media decryption make the stream stateful809- `references/response-decode-playbook.md` when the payload needs local decode before it becomes usable data810- `references/public-bootstrap-envelope-playbook.md` when a public page still needs bootstrap keys, cookies, config, or an encrypted wrapper before list replay works811- `references/delivery-gate-playbook.md` when you need to decide812813…(truncated)