Recover Protocol Buffers message schemas (names, field numbers, types, enums) statically from a compiled binary that uses protobuf, then decode/encode messages dynamically without .proto sources. Use when an app's wire format is protobuf and you need the schema — e.g. reversing a device/app protocol whose payloads are protobuf, or reading captured protobuf traffic.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add lexasoft123/qc-mcp --skill extract-embedded-protobuf --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Extract Embedded Protobuf?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lexasoft123-extract-embedded-protobuf)More formats (shields.io, HTML) on the badges page.
---
name: extract-embedded-protobuf
description: Recover Protocol Buffers message schemas (names, field numbers, types, enums) statically from a compiled binary that uses protobuf, then decode/encode messages dynamically without .proto sources. Use when an app's wire format is protobuf and you need the schema — e.g. reversing a device/app protocol whose payloads are protobuf, or reading captured protobuf traffic.
---
# Extract embedded protobuf schemas from a binary
protobuf's generated C++ embeds each `.proto`'s serialized `FileDescriptorProto` in
the binary. You can recover the full schema (message names, field numbers/types,
enums) and then build message classes at runtime — no `.proto` files or `protoc`.
## How to find them
Each embedded descriptor begins with field #1 (name): tag `0x0A`, a length byte,
then the `.proto` filename. Scan for `".proto"`, walk back to the `0x0A <len>`
marker, then let `descriptor_pb2.FileDescriptorProto` parse from there (walking the
wire format to find the blob end). This repo's `tools/extract_protos.py` does exactly
this and prints readable `.proto` output:
```bash
strings -n8 "$BIN" | grep -E "\.proto" # see which schemas are embedded
python3 tools/extract_protos.py # recover + render them
```
Also grep the mangled C++ symbols for the message set and command enum:
```bash
strings -n5 "$BIN" | grep -E "MessageReceiver|MessageSender" | sort -u
strings -n8 "$BIN" | grep -oE "<.*type=\"[A-Za-z]+\" value=\"[0-9]+\"" # sometimes an XML cmd table
```
## Decode/encode without .proto sources
Build a `DescriptorPool` from the recovered `FileDescriptorProto`s and make message
classes dynamically:
```python
from google.protobuf import descriptor_pool, message_factory, descriptor_pb2
pool = descriptor_pool.DescriptorPool()
# add google well-known deps from the Default pool first, then your files in dep order
for fdp in recovered_in_dependency_order: # e.g. Preset.proto before ProductionAutomation.proto
pool.Add(fdp)
def msg_class(fullname):
desc = pool.FindMessageTypeByName(fullname)
return (message_factory.GetMessageClass(desc)
if hasattr(message_factory,"GetMessageClass")
else message_factory.MessageFactory().GetPrototype(desc))
```
Cache the recovered descriptors as a serialized `FileDescriptorSet` (`.pb`) so you
don't rescan the binary at runtime (see `src/qc_mcp/protocol.py`).
## Notes
- The top-level command/enum map (e.g. `CortexMessageType.Enum`) tells you which
message a wire command id decodes to.
- To read raw/unknown protobuf quickly: `protoc --decode_raw < blob`, or a small
tag/wire-type walker (see `verify_frames.py:raw_protobuf_fields`).
- Sub-messages may be **gzip-compressed** inside a `bytes` field (magic `1f 8b 08`).
Worked example: recovered `Preset.proto` (BinaryPreset/Chain/Model) and
`ProductionAutomation.proto` (71 message types) from Cortex Control. See PROTOCOL.md §4-5.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!