拦截gRPC请求后Protobuf解码失败问题求助
为什么只有MitmProxy能解码该gRPC请求的Protobuf数据?
问题详情
客户端发送的gRPC负载结构如下:
gRPC header | Protobuf data [00] [00 00 00 22] [12 12 09 c3 8d 09 16 c3 93 2a c2 a5 4d 40 11 14 39 c3 ab 6b c2 a2 c3 b3 31 40 1a 05 65 6e 2d 53 45 1a 05 73 76 2d 53 45] ^^ ^^ Payload length Compressed flag
已尝试操作
失败情况
- 使用
protoc --decode_raw解码Protobuf数据,报错Failed to parse input. - 用CyberChef进行Protobuf解码,提示
Error: Exhausted Buffer - 使用
blackboxprotobufPython模块,抛出google.protobuf.message.DecodeError: Invalid Message Length异常
成功情况
MitmProxy可正常解码,结果如下:
gRPC message 0 (compressed False) [message] 2 [fixed64] 2.1 4633543028839346763 [fixed64] 2.2 4625748902140211098 [message] 3 [fixed32] 3.12 1163079022 [string] 3 sv-SE
手动解码结果
参考Google官方文档手动解码的内容:
[message] 00010 010 00010010 2 LEN 18 [fixed64] 00001 001 [11000011 10001101 00001001 00010110 11000011 10010011 00101010 11000010] 1 I64 13991157658477498000 [fixed32] 10100 101 [01001101 01000000 00010001 00010100] 20 I32 336674893 [fixed64] 00111 001 [11000011 10101011 01101011 11000010 10100010 11000011 10110011 00110001] 7 I64 3581421232503631000 [unknown] 01000 000 [00011010 00000101] 8 VARINT ??? [message] 00011 010 00000101 3 LEN 5 [fixed32] 01100 101 [01101110 00101101 01010011 01000101] 12 I32 1163079022 [string] 00011 010 00000101 [01110011 01110110 00101101 01010011 01000101] 3 LEN 7 s v - S E
核心原因分析
gRPC头负载长度与实际数据不匹配
gRPC头中标注的负载长度是0x22(34字节),但实际Protobuf数据长度是0x28(40字节)。普通Protobuf解码工具(如protoc、CyberChef)只会处理传入的原始数据,不会结合gRPC头信息做修正,当数据长度超出头部声明的长度时,工具会判定数据格式错误,导致解码失败。MitmProxy的gRPC处理逻辑差异
MitmProxy会完整捕获gRPC的帧结构(包括头部和负载),即使头部声明的长度与实际负载长度不符,它仍会尝试解析整个可用的负载数据,而非严格按照头部长度截断数据,因此能完成解码。grpc-swift-nio的特殊实现
客户端使用grpc-swift-nio/1.9.0版本,该版本可能存在帧长度计算的bug,导致发送的gRPC头中长度字段不准确。服务器端能正常解码是因为gRPC服务器通常会兼容这种长度不匹配的情况,而普通Protobuf工具没有处理该异常场景的逻辑。
注意事项
- 所有服务器响应均可正常解码
- MitmProxy可同时获取gRPC头和Protobuf数据,其他工具仅支持输入Protobuf数据
- 不确定MitmProxy解码结果是否完全正确,仅确认其无异常运行
- 客户端使用的是
grpc-swift-nio/1.9.0版本
内容的提问来源于stack exchange,提问作者WanderingCoder
相关产品推荐
相关产品推荐

