0%

protobuf-c的序列化

在复现ciscn 2023 线上初赛 pwn题目 StrangeTalkBot 中接触到了protobuf-c的序列化,记录一下!

参考文章

Language Guide (proto 2) | Protocol Buffers Documentation (protobuf.dev)

protobuf-c/protobuf-c at master · protobuf-c/protobuf-c · GitHub

关于字段注册结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
struct ProtobufCFieldDescriptor {
/** Name of the field as given in the .proto file. */
const char *name;

/** Tag value of the field as given in the .proto file. */
uint32_t id;

/** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */
ProtobufCLabel label;

/** The type of the field. */
ProtobufCType type;

/**
* The offset in bytes of the message's C structure's quantifier field
* (the `has_MEMBER` field for optional members or the `n_MEMBER` field
* for repeated members or the case enum for oneofs).
*/
unsigned quantifier_offset;

/**
* The offset in bytes into the message's C structure for the member
* itself.
*/
unsigned offset;

/**
* A type-specific descriptor.
*
* If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the
* corresponding `ProtobufCEnumDescriptor`.
*
* If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to
* the corresponding `ProtobufCMessageDescriptor`.
*
* Otherwise this field is NULL.
*/
const void *descriptor; /* for MESSAGE and ENUM types */

/** The default value for this field, if defined. May be NULL. */
const void *default_value;

/**
* A flag word. Zero or more of the bits defined in the
* `ProtobufCFieldFlag` enum may be set.
*/
uint32_t flags;

/** Reserved for future use. */
unsigned reserved_flags;
/** Reserved for future use. */
void *reserved2;
/** Reserved for future use. */
void *reserved3;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
typedef enum {
/** A well-formed message must have exactly one of this field. */
PROTOBUF_C_LABEL_REQUIRED,

/**
* A well-formed message can have zero or one of this field (but not
* more than one).
*/
PROTOBUF_C_LABEL_OPTIONAL,

/**
* This field can be repeated any number of times (including zero) in a
* well-formed message. The order of the repeated values will be
* preserved.
*/
PROTOBUF_C_LABEL_REPEATED,

/**
* This field has no label. This is valid only in proto3 and is
* equivalent to OPTIONAL but no "has" quantifier will be consulted.
*/
PROTOBUF_C_LABEL_NONE,
} ProtobufCLabel;

/**
* Field value types.
*
* \see [Scalar Value Types] in the Protocol Buffers documentation.
*
* [Scalar Value Types]:
* https://developers.google.com/protocol-buffers/docs/proto#scalar
*/
typedef enum {
PROTOBUF_C_TYPE_INT32, /**< int32 0 */
PROTOBUF_C_TYPE_SINT32, /**< signed int32 1 */
PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) 2 */
PROTOBUF_C_TYPE_INT64, /**< int64 3 */
PROTOBUF_C_TYPE_SINT64, /**< signed int64 4 */
PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) 5 */
PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 6 */
PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) 7 */
PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 8 */
PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) 9 */
PROTOBUF_C_TYPE_FLOAT, /**< float A */
PROTOBUF_C_TYPE_DOUBLE, /**< double B */
PROTOBUF_C_TYPE_BOOL, /**< boolean C */
PROTOBUF_C_TYPE_ENUM, /**< enumerated type D */
PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string E */
PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence F */
PROTOBUF_C_TYPE_MESSAGE, /**< nested message 10 */
} ProtobufCType;
本题中对应的注册文件
1
2
3
4
5
6
7
8
syntax = "proto2";

message devicemsg {
required sint64 actionid=1;
required sint64 msgidx=2;
required sint64 msgsize=3;
required bytes msgcontent=4;
}
生成python文件

生成的文件默认为<文件名_pd2.py>,如ctf_pd2.py

1
protoc --python_out=./ ./ctf.proto
使用
1
2
3
4
5
6
7
import ctf_pb2
message = test_pb2.devicemsg()
message.actionid = 1
message.msgidx = idx
message.msgsize = size
message.msgcontent = msg
payload = message.SerializeToString()
-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道