| name | net-reverse |
| description | Network and protocol reverse-engineering for authorized captures. Use when the user asks for 网络逆向, 抓包, PCAP, HAR, Wireshark, tshark, WebSocket, protobuf, gRPC, 自定义协议, thick-client framing, or to recover a session/state machine from traffic. Do not use for unauthorized MITM, mass sniffing, or attacking third-party hosts. |
Net Reverse
Recover a protocol from traffic, then a parser. Distilled from reverse-skill protocol-reverse and the protocol-reverse-engineering skill: conversations first, then framing, then fields, then a client. Not a scanner.
Scope
Allowed sources:
- PCAP / PCAPNG / HAR / mitm dump the guest handed over
- capture on an interface the guest owns (their lab VM, their loopback, their app)
- TLS keys the guest already has (
SSLKEYLOGFILE, server cert they control)
Forbidden: transparent MITM on a network they do not administer; replay against a host they did not name as in-scope.
Loop
preserve → conversations → identify L7 → frame → fields → parser → (optional) authorized replay
1. Preserve
Copy the capture. Hash it. Note snaplen (truncated packets lie). Do not edit the original.
cp -- capture.pcap capture.pcap.bak
sha256sum capture.pcap
capinfos capture.pcap 2>/dev/null || tshark -r capture.pcap -q -z io,phs
2. Conversations before bytes
tshark -r capture.pcap -q -z conv,tcp
tshark -r capture.pcap -q -z endpoints,ip
tshark -r capture.pcap -q -z io,phs
Name the pair that matters (client ↔ server, ports). Follow that stream. Ignore the rest until the primary session is understood.
tshark -r capture.pcap -q -z follow,tcp,ascii,0
3. Identify L7
Cheap signatures, then stop guessing:
| Hint | Likely |
|---|
GET / HTTP/1. | HTTP → hand $api-reverse for the contract |
16 03 TLS record | TLS. Need guest keylog before payload work |
GET / + Upgrade: websocket | WebSocket |
PRI * HTTP/2 / many small binary frames | HTTP/2 or gRPC |
\x00 length + .proto strings / grpc content-type | protobuf / gRPC |
| magic at offset 0, stable header size | custom binary |
| JSON / msgpack after a small header | framed RPC |
Encrypted blob with entropy > ~7.5 and no keylog: document the envelope (SNI, ALPN, sizes, timing). Do not invent plaintext.
TLS with guest keylog:
export SSLKEYLOGFILE=/path/to/keys.log
tshark -r capture.pcap -o "tls.keylog_file:$SSLKEYLOGFILE" -Y http -T fields -e http.request.method -e http.host -e http.request.uri
4. Frame the message
Compare two or more sessions of the same action (login, send, heartbeat). Diff what is constant vs what moves.
Look for, in order:
- magic / signature
- version
- type / opcode
- length (inclusive or payload-only — prove it)
- sequence / session id
- checksum / HMAC (name the range it covers)
- payload (maybe another nested TLV)
Endianness: try both; the length field that matches remaining bytes is the winner.
Protobuf: if .proto exists, compile it. If not, treat length-delimited records and recover field numbers from repeated samples; do not fake message names.
WebSocket: reassemble, then treat opcode 1 as text (maybe JSON → $api-reverse / $js-reverse), opcode 2 as binary (this lane).
5. Field table (the nail)
Every field gets a row. "some bytes" is not a field.
| Off | Size | Name | Evidence |
|---|
| 0 | 4 | magic | same in all packets, ASCII PROT |
| 4 | 2 | type | 1=hello, 3=data (two sessions) |
| 6 | 4 | len | equals payload bytes |
Keep a state machine: HELLO → ACK → DATA* → CLOSE. Heartbeats are first-class messages.
6. Parser, then optional replay
Write a parser that consumes the capture and prints the table. The parser is the proof. A dissector or struct decoder counts.
Replay only against a service the guest named (their mock, their staging, their loopback). Replay is for proving the framing, not for hammering a vendor.
Mobile / thick client on a guest-owned device: capture via their proxy or tcpdump on their emulator. Certificate pinning is an analysis obstacle — locate the pin (APK Java/TrustManager / native). Unpinning scripts only on that owned build. Then the HTTP part goes to $api-reverse.
Anti-stuck
- Truncated snaplen → recapture, do not "fix" lengths.
- Same header, random payload → encrypted or compressed; say which, with entropy.
- One sample only → ask for a second session of the same action, or vary one input.
- HTTP-looking traffic with a custom sign header →
$api-reverse (+ $js-reverse if browser).
Completion
- Transport + L7 identity.
- Field table + state machine.
- Parser path and the command that dumps one session.
- What is still ciphertext / unknown.
- If HTTP/JSON: hand off
$api-reverse. If sign lives in JS: $js-reverse.