Binary bytes still carry structure
A protobuf message stores numbered fields and wire types. The bytes keep field numbers, values and message boundaries. They do not carry the original field names or the full .proto file. A field with wire type LEN may be a string, raw bytes, a packed list or another message. That is why one decoded capture does not describe the API.
We recover the schema from every place the APK knows it. Generated Java or Kotlin classes may contain message names, field numbers, parser methods, enum values and descriptor data. Flutter, native JNI and bundled assets can hold the same facts in other forms. Runtime messages then show which fields are set for login, search, upload, refresh and later calls.
Recover field meaning across the full app
Field numbers must stay stable because they identify fields on the protobuf wire. We group captured messages by endpoint and direction, decode their tags, then match each value to the code that created it. This separates an integer ID from an enum, a UTF-8 string from arbitrary bytes, and a nested message from an opaque encrypted value.
- Map request and response message types for every app workflow.
- Recover repeated fields, maps,
oneofbranches and nested messages. - Record unknown fields so a newer server response does not break the client.
- Find protobuf data wrapped in HTTP, gRPC, WebSocket or a custom frame.
- Trace values added before serialization, including signatures and encrypted fields.
Byte order matters when requests are signed
Official protobuf documentation says serialization order is not guaranteed by default. Two valid encoders can produce different bytes for the same logical message. That difference matters when the app hashes or signs serialized bytes. We trace the exact point where the APK serializes and signs the message, then reproduce that byte sequence in both delivered clients.
The reconstructed .proto files are checked against real requests and responses. A guessed field name is marked with a clear useful name in the client, while its original field number and wire behavior stay exact.
The full delivery
You receive a callable API for the full APK in Python and JavaScript/TypeScript, plus a Postman collection. The clients cover every recovered endpoint and workflow. They create fresh signatures, encrypt requests, decrypt responses, keep authentication and session state, and follow the same request order as the app.
Each client includes clear input models, parsed outputs, refresh behavior, uploads, downloads, streaming events and useful errors where the app uses them. We test the delivery against the live service so it runs without copied requests or old tokens.
Sources
Reviewed 30 August 2026 · SReverse research desk