//
// Test module using proto2 syntax.
//
// This module is used in test cases, and also serves as an example of how to
// define a YARA module using a protocol buffer.
//
// There are two versions of protobuf, "proto2" and "proto3". If this is omitted
// the default is "proto2", but it's recommendable to make it explicit.
syntax = "proto2";
// This import is required for defining a YARA module, it contains definitions
// that are common to all modules.
import "yara.proto";
// This is not strictly required, but it prevents name collisions with other
// YARA modules.
package test_proto2;
// This option section is also required, it gives YARA information about
// the module being defined.
option (yara.module_options) = {
// The module's name. This is the string used in `import` statements in YARA
// rules (e.g. import "test_proto2"). This field is required.
name : "test_proto2"
// The protobuf message that defines the top-level structure of the module.
// A .proto file can contain multiple message definitions, usually organized
// in a hierarchical structure in which one message has fields that are other
// messages. YARA needs to know which of those message definitions describes
// the top-level structure for the module. In this case the root message is
// "test_proto2.TestProto2" which indicates that the "test_proto2" module
// will have the fields defined in the "TestProto2" message. Notice that
// the "test_proto2." prefix comes after the package name.
root_message: "test_proto2.TestProto2"
// The name of the Rust module that contains the code for this module. A
// module with this name must exists under src/modules. In this case the
// module name is "test_proto2", we can create a module with that name in
// two ways: by creating a file "test_proto2.rs" under src/modules, or by
// creating a "test_proto2" directory under src/modules and putting a
// "mod.rs" file inside of it.
//
// Notice however that this is optional, as YARA modules can consists only
// in the data structure defined by this proto file, and don't need to have
// any associated code.
rust_module: "test_proto2"
// The name of the feature that controls whether this module is compiled or
// not. A feature with this name must be added to the Cargo.toml file.
cargo_feature: "test_proto2-module"
};
// Top-level structure for this module.
//
// In a YARA rule, after importing the module with `import "test_proto2"`, you
// can access the fields in this structure, as in the following examples:
//
// test_proto2.int32_zero == 0
// test_proto2.string_foo == "foo"
//
// Notice that proto2 fields must be either optional or required. Optional
// fields don't need to be explicitly set to some value, they can remain
// empty. If a field is empty it will appear to YARA as undefined. In the
// other hand, required fields must be explicitly set to some value before
// the structure is passed to YARA.
//
// In proto3 you don't need to specify if fields are optional or required,
// they are always optional and you don't need to set their values explicitly.
// However, fields for which you don't set a value explicitly are considered
// to have the default value for the type. Numeric values default to 0, and
// string values default to an empty string. These fields are never undefined
// to YARA, they always have some value, either their default values or the
// value explicitly set while filling the structure.
message TestProto2 {
// Numeric values initialized to 0 by the module.
required int32 int32_zero = 1;
required int64 int64_zero = 2;
required sint32 sint32_zero = 3;
required sint64 sint64_zero = 4;
required uint32 uint32_zero = 5;
required uint64 uint64_zero = 6;
required fixed32 fixed32_zero = 7;
required fixed64 fixed64_zero = 8;
required sfixed32 sfixed32_zero = 9;
required sfixed64 sfixed64_zero = 10;
required float float_zero = 11;
required double double_zero = 12;
// Numeric values initialized to 1 by the module.
required int32 int32_one = 21;
required int64 int64_one = 22;
required sint32 sint32_one = 23;
required sint64 sint64_one = 24;
required uint32 uint32_one = 25;
required uint64 uint64_one = 26;
required fixed32 fixed32_one = 27;
required fixed64 fixed64_one = 28;
required sfixed32 sfixed32_one = 29;
required sfixed64 sfixed64_one = 30;
required float float_one = 31;
required double double_one = 32;
// Numeric values that remain undefined.
optional int32 int32_undef = 41;
optional int64 int64_undef = 42;
optional sint32 sint32_undef = 43;
optional sint64 sint64_undef = 44;
optional uint32 uint32_undef = 45;
optional uint64 uint64_undef = 46;
optional fixed32 fixed32_undef = 47;
optional fixed64 fixed64_undef = 48;
optional sfixed32 sfixed32_undef = 49;
optional sfixed64 sfixed64_undef = 50;
optional float float_undef = 51;
optional double double_undef = 52;
// String values.
required string string_foo = 61 [(yara.field_options).lowercase = true];
required string string_bar = 62;
optional string string_undef = 63;
required bytes bytes_foo = 64;
required bytes bytes_bar = 65;
required bytes bytes_raw = 66;
optional bytes bytes_undef = 67;
enum Enumeration {
ITEM_0 = 0;
ITEM_1 = 1;
ITEM_2 = 2 [(yara.enum_value).i64 = 0x7fffffffffff];
ITEM_3 = 3 [(yara.enum_value).i64 = -1];
}
optional Enumeration enumeration = 100;
optional NestedProto2 nested = 102;
repeated int64 array_int64 = 150;
repeated float array_float = 151;
repeated bool array_bool = 152;
repeated string array_string = 153;
repeated NestedProto2 array_struct = 154;
map<string, NestedProto2> map_string_struct = 200;
map<string, int64> map_string_int64 = 201;
map<string, string> map_string_string = 202;
map<string, bool> map_string_bool = 203;
map<string, float> map_string_float = 204;
map<int64, NestedProto2> map_int64_struct = 300;
map<int64, int64> map_int64_int64 = 301;
map<int64, string> map_int64_string = 302;
map<int64, bool> map_int64_bool = 303;
map<int64, float> map_int64_float = 304;
optional int64 timestamp = 305 [(yara.field_options).fmt = "t"];
// This field will be visible in YARA as `bool_yara` instead of `bool_proto`.
optional bool bool_proto = 350 [(yara.field_options).name = "bool_yara"];
// This field won't be visible to YARA.
optional bool ignored = 351 [(yara.field_options).ignore = true];
// This field will be visible in YARA as `items` instead of `Enumeration2`.
enum Enumeration2 {
option (yara.enum_options).name = "items";
ITEM_4 = 0;
ITEM_5 = 1;
}
optional uint64 file_size = 400;
// This field is accessible only if the features "foo" (or "FOO") and "bar"
// are enabled while compiling the YARA rules.
optional uint64 requires_foo_and_bar = 500 [
(yara.field_options) = {
acl: [
{
accept_if: ["foo", "FOO"],
error_title: "foo is required",
error_label: "this field was used without foo"
},
{
accept_if: "bar",
error_title: "bar is required",
error_label: "this field was used without bar"
},
{
reject_if: "baz",
error_title: "baz is forbidden",
error_label: "this field was used with baz"
}
]
}
];
optional string deprecated = 501 [ (yara.field_options).deprecation_notice = {
text: "don't use",
help: "use `foo` instead",
replacement: "foo"
}];
// The metadata received by the module is copied into this field.
optional bytes metadata = 502;
}
enum TopLevelEnumeration {
ITEM_0x1000 = 0x1000;
ITEM_0x2000 = 0x2000;
}
enum InlineEnumeration {
option (yara.enum_options).inline = true;
INLINE_0x1000 = 0x1000;
INLINE_0x2000 = 0x2000;
}
message NestedProto2 {
optional int32 nested_int32_zero = 1;
optional int64 nested_int64_zero = 2;
optional int32 nested_int32_one = 3;
optional int64 nested_int64_one = 4;
optional bool nested_bool = 5;
optional string nested_string = 6;
repeated int64 nested_array_int64 = 7;
enum NestedEnumeration {
ITEM_0 = 0;
ITEM_1 = 1;
}
}