syntax = "proto2";

import "yara.proto";
import "yaml.proto";

package pe;

option (yara.module_options) = {
  name : "pe"
  root_message: "pe.PE"
  rust_module: "pe"
  cargo_feature: "pe-module"
};

message PE {
  required bool is_pe = 1;
  optional Machine machine = 2;
  optional Subsystem subsystem = 3;
  optional Version os_version = 4;
  optional Version subsystem_version = 5;
  optional Version image_version = 6;
  optional Version linker_version = 7;
  optional OptHdrMagic opthdr_magic = 8;
  optional uint32 characteristics = 9;
  optional uint32 dll_characteristics = 10;
  optional uint32 timestamp = 11 [(yaml.field).fmt = "t"];
  optional uint64 image_base = 12;
  optional uint32 checksum = 13;
  optional uint32 base_of_code = 14;
  optional uint32 base_of_data = 15;

  // Entry point as a file offset.
  optional uint32 entry_point = 16;

  // Entry point as it appears in the PE header (RVA).
  optional uint32 entry_point_raw = 17;

  optional string dll_name = 18;
  optional uint32 export_timestamp = 19 [(yaml.field).fmt = "t"];

  optional uint32 section_alignment = 20;
  optional uint32 file_alignment = 21;
  optional uint32 loader_flags = 22;

  optional uint32 size_of_optional_header = 23;
  optional uint32 size_of_code = 24;
  optional uint32 size_of_initialized_data = 25;
  optional uint32 size_of_uninitialized_data = 26;
  optional uint32 size_of_image = 27;
  optional uint32 size_of_headers = 28;

  optional uint64 size_of_stack_reserve = 29;
  optional uint64 size_of_stack_commit = 30;
  optional uint64 size_of_heap_reserve = 31;
  optional uint64 size_of_heap_commit = 32;

  optional uint32 pointer_to_symbol_table = 33;
  optional uint32 win32_version_value = 34;
  optional uint32 number_of_symbols = 35;
  optional uint32 number_of_rva_and_sizes = 36;
  optional uint32 number_of_sections = 37;
  optional uint64 number_of_imported_functions = 38;
  optional uint64 number_of_delayed_imported_functions = 39;
  optional uint64 number_of_resources = 40;
  optional uint64 number_of_version_infos = 41;
  optional uint64 number_of_imports = 42;
  optional uint64 number_of_delayed_imports = 43;
  optional uint64 number_of_exports = 44;
  optional uint64 number_of_signatures = 45;

  map<string, string> version_info = 46;
  repeated KeyValue version_info_list = 47;
  optional RichSignature rich_signature = 48;
  optional bytes pdb_path = 49;
  repeated Section sections = 50;
  repeated DirEntry data_directories = 51;

  optional uint64 resource_timestamp = 52 [(yaml.field).fmt = "t"];
  // TODO: implement resource_version?
  optional Version resource_version = 53;
  repeated Resource resources = 54;
  repeated Import import_details = 55;
  repeated Import delayed_import_details = 56;
  repeated Export export_details = 57;
  optional bool is_signed = 58;
  repeated Signature signatures = 59;
  
  optional Overlay overlay = 60;
}

message Version {
  required uint32 major = 1;
  required uint32 minor = 2;
}

message KeyValue {
  required string key = 1;
  required string value = 2;
}

message DirEntry {
  required uint32 virtual_address = 1;
  required uint32 size = 2;
}

message Resource {
  required uint32 length = 1;
  required uint32 rva = 2;
  optional uint32 offset = 3;
  optional ResourceType type = 4;
  optional uint32 id = 5;
  optional uint32 language = 6;
  optional bytes type_string = 7;
  optional bytes name_string = 8;
  optional bytes language_string = 9;
}

message Import {
  required string library_name = 1;
  required uint64 number_of_functions = 2;
  repeated Function functions = 3;
}

message Export {
  optional string name= 1;
  required uint32 ordinal = 2;
  required uint32 rva = 3;
  optional uint32 offset = 4;
  optional string forward_name = 5;
}

message Function {
  optional string name = 1;
  optional uint32 ordinal = 2;
  required uint32 rva = 3;
}


message Signature {
  optional string subject = 1;
  optional string issuer = 2;
  optional string thumbprint = 3;
  optional int64 version = 4;
  optional string algorithm = 5;
  optional string algorithm_oid = 6;
  optional string serial = 7;
  optional int64 not_before = 8 [(yaml.field).fmt = "t"];
  optional int64 not_after = 9 [(yaml.field).fmt = "t"];
  optional bool verified = 10;
  optional string digest_alg = 11;
  optional string digest = 12;
  optional string file_digest = 13;
  optional uint64 number_of_certificates = 14;
  optional uint64 number_of_countersignatures = 15;
  optional SignerInfo signer_info = 16;
  repeated Certificate certificates = 17;
  repeated CounterSignature countersignatures = 18;
}

message SignerInfo {
  optional string program_name = 1;
  optional string digest = 2;
  optional string digest_alg = 3;
  repeated Certificate chain = 4;
}

message Certificate {
  optional string issuer = 1;
  optional string subject = 2;
  optional string thumbprint = 3;
  optional int64 version = 4;
  optional string algorithm = 5;
  optional string algorithm_oid = 6;
  optional string serial = 7;
  optional int64 not_before = 8 [(yaml.field).fmt = "t"];
  optional int64 not_after = 9 [(yaml.field).fmt = "t"];
}

message CounterSignature {
  optional bool verified = 1;
  optional int64 sign_time = 2 [(yaml.field).fmt = "t"];
  optional string digest = 12;
  optional string digest_alg = 3;
  repeated Certificate chain = 4;
}

///  https://learn.microsoft.com/en-us/windows/win32/menurc/resource-types?redirectedfrom=MSDN
enum ResourceType {
  option (yara.enum_options).inline = true;
  RESOURCE_TYPE_CURSOR = 1;
  RESOURCE_TYPE_BITMAP = 2;
  RESOURCE_TYPE_ICON = 3;
  RESOURCE_TYPE_MENU = 4;
  RESOURCE_TYPE_DIALOG = 5;
  RESOURCE_TYPE_STRING = 6;
  RESOURCE_TYPE_FONTDIR = 7;
  RESOURCE_TYPE_FONT = 8;
  RESOURCE_TYPE_ACCELERATOR = 9;
  RESOURCE_TYPE_RCDATA = 10;
  RESOURCE_TYPE_MESSAGETABLE = 11;
  RESOURCE_TYPE_GROUP_CURSOR = 12;
  // 13 is missing
  RESOURCE_TYPE_GROUP_ICON = 14;
  // 15 is missing
  RESOURCE_TYPE_VERSION = 16;
  RESOURCE_TYPE_DLGINCLUDE = 17;
  // 18 is missing
  RESOURCE_TYPE_PLUGPLAY = 19;
  RESOURCE_TYPE_VXD = 20;
  RESOURCE_TYPE_ANICURSOR = 21;
  RESOURCE_TYPE_ANIICON = 22;
  RESOURCE_TYPE_HTML = 23;
  RESOURCE_TYPE_MANIFEST = 24;
}

message Section {
  // The section's name as listed in the section table. The data type is `bytes`
  // instead of `string` so that it can accommodate invalid UTF-8 content. The
  // length is 8 bytes at most.
  required bytes name = 1;
  // For section names longer than 8 bytes, the name in the section table (and
  // in the `name` field) contains a forward slash (/) followed by an ASCII
  // representation of a decimal number that is an offset into the string table.
  // (examples: "/4", "/123") This mechanism is described in the MSDN and used
  // by GNU compilers.
  //
  // When this scenario occurs, the `full_name` field holds the actual section
  // name. In all other cases, it simply duplicates the content of the `name`
  // field.
  //
  // See: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header#members
  required bytes full_name = 2;
  required uint32 characteristics = 3;
  required uint32 raw_data_size = 4;
  required uint32 raw_data_offset = 5;
  required uint32 virtual_address = 6;
  required uint32 virtual_size = 7;
  required uint32 pointer_to_relocations = 8;
  required uint32 pointer_to_line_numbers = 9;
  required uint32 number_of_relocations = 10;
  required uint32 number_of_line_numbers = 11;
}

message RichSignature {
  required uint32 offset = 1;
  required uint32 length = 2;
  required uint32 key = 3;
  required bytes raw_data = 4;
  required bytes clear_data = 5;
  repeated RichTool tools = 6;
}

message RichTool {
  required uint32 toolid = 1;
  required uint32 version = 2;
  required uint32 times = 3;
}

message Overlay {
  required uint64 offset = 1;
  required uint64 size = 2;
}

enum Machine {
  option (yara.enum_options).inline = true;
  MACHINE_UNKNOWN   = 0x0000;
  MACHINE_AM33      = 0x01d3;
  MACHINE_AMD64     = 0x8664;
  MACHINE_ARM       = 0x01c0;
  MACHINE_ARMNT     = 0x01c4;
  MACHINE_ARM64     = 0xaa64;
  MACHINE_EBC       = 0x0ebc;
  MACHINE_I386      = 0x014c;
  MACHINE_IA64      = 0x0200;
  MACHINE_M32R      = 0x9041;
  MACHINE_MIPS16    = 0x0266;
  MACHINE_MIPSFPU   = 0x0366;
  MACHINE_MIPSFPU16 = 0x0466;
  MACHINE_POWERPC   = 0x01f0;
  MACHINE_POWERPCFP = 0x01f1;
  MACHINE_R4000     = 0x0166;
  MACHINE_SH3       = 0x01a2;
  MACHINE_SH3DSP    = 0x01a3;
  MACHINE_SH4       = 0x01a6;
  MACHINE_SH5       = 0x01a8;
  MACHINE_THUMB     = 0x01c2;
  MACHINE_WCEMIPSV2 = 0x0169;
}

enum Subsystem {
  option (yara.enum_options).inline = true;
  SUBSYSTEM_UNKNOWN                  = 0;
  SUBSYSTEM_NATIVE                   = 1;
  SUBSYSTEM_WINDOWS_GUI              = 2;
  SUBSYSTEM_WINDOWS_CUI              = 3;
  SUBSYSTEM_OS2_CUI                  = 5;
  SUBSYSTEM_POSIX_CUI                = 7;
  SUBSYSTEM_NATIVE_WINDOWS           = 8;
  SUBSYSTEM_WINDOWS_CE_GUI           = 9;
  SUBSYSTEM_EFI_APPLICATION          = 10;
  SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER  = 11;
  SUBSYSTEM_EFI_RUNTIME_DRIVER       = 12;
  SUBSYSTEM_EFI_ROM_IMAGE            = 13;
  SUBSYSTEM_XBOX                     = 14;
  SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16;
}

enum ImportFlags {
  option (yara.enum_options).inline = true;
  IMPORT_STANDARD = 0x01;
  IMPORT_DELAYED = 0x02;
  IMPORT_ANY = 0x03;
}

enum OptHdrMagic {
  IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
  IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
}

enum Characteristics {
  option (yara.enum_options).inline = true;
  // Relocation info stripped from file.
  RELOCS_STRIPPED         = 0x0001;
  // File is executable (i.e. no unresolved external references).
  EXECUTABLE_IMAGE        = 0x0002;
  // Line numbers stripped from file.
  LINE_NUMS_STRIPPED      = 0x0004;
  // Local symbols stripped from file.
  LOCAL_SYMS_STRIPPED     = 0x0008;
  // Aggressively trim working set
  AGGRESIVE_WS_TRIM       = 0x0010;
  // App can handle >2gb addresses
  LARGE_ADDRESS_AWARE     = 0x0020;
  // Bytes of machine word are reversed.
  BYTES_REVERSED_LO       = 0x0080;
  // 32 bit word machine.
  MACHINE_32BIT           = 0x0100;
  // Debugging info stripped from file in .DBG file
  DEBUG_STRIPPED          = 0x0200;
  // If Image is on removable media, copy and run from the swap file.
  REMOVABLE_RUN_FROM_SWAP = 0x0400;
  // If Image is on Net, copy and run from the swap file.
  NET_RUN_FROM_SWAP       = 0x0800;
  // System File.
  SYSTEM                  = 0x1000;
  // File is a DLL.s
  DLL                     = 0x2000;
  // File should only be run on a UP machine
  UP_SYSTEM_ONLY          = 0x4000;
  // Bytes of machine word are reversed.
  BYTES_REVERSED_HI       = 0x8000;
}

enum OptionalMagic {
  option (yara.enum_options).inline = true;
  IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
  IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
  IMAGE_ROM_OPTIONAL_HDR_MAGIC  = 0x107;
}

enum DirectoryEntry {
  option (yara.enum_options).inline = true;
  IMAGE_DIRECTORY_ENTRY_EXPORT        =  0  [(yara.enum_value).i64 = 0];
  IMAGE_DIRECTORY_ENTRY_IMPORT        =  1  [(yara.enum_value).i64 = 1];
  IMAGE_DIRECTORY_ENTRY_RESOURCE      =  2  [(yara.enum_value).i64 = 2];
  IMAGE_DIRECTORY_ENTRY_EXCEPTION     =  3  [(yara.enum_value).i64 = 3];
  IMAGE_DIRECTORY_ENTRY_SECURITY      =  4  [(yara.enum_value).i64 = 4];
  IMAGE_DIRECTORY_ENTRY_BASERELOC     =  5  [(yara.enum_value).i64 = 5];
  IMAGE_DIRECTORY_ENTRY_DEBUG         =  6  [(yara.enum_value).i64 = 6];
  // IMAGE_DIRECTORY_ENTRY_COPYRIGHT and IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
  // have the same value (7).
  IMAGE_DIRECTORY_ENTRY_COPYRIGHT     =  7  [(yara.enum_value).i64 = 7];
  IMAGE_DIRECTORY_ENTRY_ARCHITECTURE  =  8  [(yara.enum_value).i64 = 7];
  IMAGE_DIRECTORY_ENTRY_GLOBALPTR     =  9  [(yara.enum_value).i64 = 8];
  IMAGE_DIRECTORY_ENTRY_TLS           =  10 [(yara.enum_value).i64 = 9];
  IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    = 11 [(yara.enum_value).i64 = 10];
  IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   = 12 [(yara.enum_value).i64 = 11];
  IMAGE_DIRECTORY_ENTRY_IAT            = 13 [(yara.enum_value).i64 = 12];
  IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   = 14 [(yara.enum_value).i64 = 13];
  IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 15 [(yara.enum_value).i64 = 14];
}

enum SectionCharacteristics {
  option (yara.enum_options).inline = true;
  SECTION_NO_PAD                 = 1 [(yara.enum_value).i64 = 0x00000008];
  SECTION_CNT_CODE               = 2 [(yara.enum_value).i64 = 0x00000020];
  SECTION_CNT_INITIALIZED_DATA   = 3 [(yara.enum_value).i64 = 0x00000040];
  SECTION_CNT_UNINITIALIZED_DATA = 4 [(yara.enum_value).i64 = 0x00000080];
  SECTION_LNK_OTHER              = 5 [(yara.enum_value).i64 = 0x00000100];
  SECTION_LNK_INFO               = 6 [(yara.enum_value).i64 = 0x00000200];
  SECTION_LNK_REMOVE             = 7 [(yara.enum_value).i64 = 0x00000800];
  SECTION_LNK_COMDAT             = 8 [(yara.enum_value).i64 = 0x00001000];
  SECTION_NO_DEFER_SPEC_EXC      = 9 [(yara.enum_value).i64 = 0x00004000];
  SECTION_GPREL                  = 10 [(yara.enum_value).i64 = 0x00008000];
  SECTION_ALIGN_1BYTES           = 11 [(yara.enum_value).i64 = 0x00100000];
  SECTION_ALIGN_2BYTES           = 12 [(yara.enum_value).i64 = 0x00200000];
  SECTION_ALIGN_4BYTES           = 13 [(yara.enum_value).i64 = 0x00300000];
  SECTION_ALIGN_8BYTES           = 14 [(yara.enum_value).i64 = 0x00400000];
  SECTION_ALIGN_16BYTES          = 15 [(yara.enum_value).i64 = 0x00500000];
  SECTION_ALIGN_32BYTES          = 16 [(yara.enum_value).i64 = 0x00600000];
  SECTION_ALIGN_64BYTES          = 17 [(yara.enum_value).i64 = 0x00700000];
  SECTION_ALIGN_128BYTES         = 18 [(yara.enum_value).i64 = 0x00800000];
  SECTION_ALIGN_256BYTES         = 19 [(yara.enum_value).i64 = 0x00900000];
  SECTION_ALIGN_512BYTES         = 20 [(yara.enum_value).i64 = 0x00A00000];
  SECTION_ALIGN_1024BYTES        = 21 [(yara.enum_value).i64 = 0x00B00000];
  SECTION_ALIGN_2048BYTES        = 22 [(yara.enum_value).i64 = 0x00C00000];
  SECTION_ALIGN_4096BYTES        = 23 [(yara.enum_value).i64 = 0x00D00000];
  SECTION_ALIGN_8192BYTES        = 24 [(yara.enum_value).i64 = 0x00E00000];
  SECTION_ALIGN_MASK             = 25 [(yara.enum_value).i64 = 0x00F00000];
  SECTION_LNK_NRELOC_OVFL        = 26 [(yara.enum_value).i64 = 0x01000000];
  SECTION_MEM_DISCARDABLE        = 27 [(yara.enum_value).i64 = 0x02000000];
  SECTION_MEM_NOT_CACHED         = 28 [(yara.enum_value).i64 = 0x04000000];
  SECTION_MEM_NOT_PAGED          = 29 [(yara.enum_value).i64 = 0x08000000];
  SECTION_MEM_SHARED             = 30 [(yara.enum_value).i64 = 0x10000000];
  SECTION_MEM_EXECUTE            = 31 [(yara.enum_value).i64 = 0x20000000];
  SECTION_MEM_READ               = 32 [(yara.enum_value).i64 = 0x40000000];
  SECTION_MEM_WRITE              = 33 [(yara.enum_value).i64 = 0x80000000];
  SECTION_SCALE_INDEX            = 34 [(yara.enum_value).i64 = 0x00000001];
}

enum DllCharacteristics {
  option (yara.enum_options).inline = true;
  HIGH_ENTROPY_VA       = 0x0020;
  DYNAMIC_BASE          = 0x0040;
  FORCE_INTEGRITY       = 0x0080;
  NX_COMPAT             = 0x0100;
  NO_ISOLATION          = 0x0200;
  NO_SEH                = 0x0400;
  NO_BIND               = 0x0800;
  APPCONTAINER          = 0x1000;
  WDM_DRIVER            = 0x2000;
  GUARD_CF              = 0x4000;
  TERMINAL_SERVER_AWARE = 0x8000;
}