Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 166 additions & 42 deletions examples/custom-module/Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions examples/custom-module/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ protobuf = "3.7.2"
# Compiles `proto/custom_test.proto` into Rust code at build time. The
# `pure` mode is selected so that no external `protoc` binary is required.
protobuf-codegen = "3.7.2"
# Provides `yara.proto`, which defines the custom protobuf options used by
# YARA-X module schemas.
yara-x-proto = { path = "../../proto" }
16 changes: 16 additions & 0 deletions examples/custom-module/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,26 @@ fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=proto");

let out_dir = std::path::PathBuf::from(
std::env::var_os("OUT_DIR").expect("OUT_DIR must be set"),
);
let yara_proto_dir = out_dir.join("yara-proto");
std::fs::create_dir_all(&yara_proto_dir)
.expect("failed to create yara.proto include directory");
std::fs::write(
yara_proto_dir.join(yara_x_proto::YARA_PROTO_FILE_NAME),
yara_x_proto::YARA_PROTO,
)
.expect("failed to write yara.proto");
let yara_proto_path =
yara_proto_dir.join(yara_x_proto::YARA_PROTO_FILE_NAME);

protobuf_codegen::Codegen::new()
.pure()
.cargo_out_dir("protos")
.include("proto")
.include(yara_proto_dir)
.input(yara_proto_path)
.input("proto/foobar.proto")
.run_from_script();
}
7 changes: 7 additions & 0 deletions examples/custom-module/proto/foobar.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ syntax = "proto2";

package foobar;

import "yara.proto";

option (yara.module_options) = {
name: "foobar"
root_message: "foobar.Foobar"
};

message Foobar {
optional uint64 count = 1;
optional string label = 2;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modules/crx/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap as HashMap;
use std::fmt::Write;
use std::io::{Cursor, Read, Seek};

Expand Down
250 changes: 123 additions & 127 deletions lib/src/modules/pe/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,9 @@ impl<'a> PE<'a> {
if let Ok(rva) = TryInto::<u32>::try_into(thunk) {
func.name = self
.parse_at_rva(rva, Self::parse_import_by_name)
.and_then(|s| String::from_utf8(s.to_vec()).ok())
.and_then(|s| {
from_utf8(s).ok().map(|s| s.to_string())
})
}
}

Expand Down Expand Up @@ -3277,130 +3279,124 @@ fn oleaut32_ord_to_name(ordinal: u16) -> Option<&'static str> {

/// Convert ordinal number to function name for wsock32.dll and ws2_32.dll.
fn wsock32_ord_to_name(ordinal: u16) -> Option<&'static str> {
static WSOCK32_ORD_TO_NAME: OnceLock<HashMap<u16, &'static str>> =
OnceLock::new();

let m = WSOCK32_ORD_TO_NAME.get_or_init(|| {
let mut m = HashMap::new();
m.insert(1, "accept");
m.insert(2, "bind");
m.insert(3, "closesocket");
m.insert(4, "connect");
m.insert(5, "getpeername");
m.insert(6, "getsockname");
m.insert(7, "getsockopt");
m.insert(8, "htonl");
m.insert(9, "htons");
m.insert(10, "ioctlsocket");
m.insert(11, "inet_addr");
m.insert(12, "inet_ntoa");
m.insert(13, "listen");
m.insert(14, "ntohl");
m.insert(15, "ntohs");
m.insert(16, "recv");
m.insert(17, "recvfrom");
m.insert(18, "select");
m.insert(19, "send");
m.insert(20, "sendto");
m.insert(21, "setsockopt");
m.insert(22, "shutdown");
m.insert(23, "socket");
m.insert(24, "GetAddrInfoW");
m.insert(25, "GetNameInfoW");
m.insert(26, "WSApSetPostRoutine");
m.insert(27, "FreeAddrInfoW");
m.insert(28, "WPUCompleteOverlappedRequest");
m.insert(29, "WSAAccept");
m.insert(30, "WSAAddressToStringA");
m.insert(31, "WSAAddressToStringW");
m.insert(32, "WSACloseEvent");
m.insert(33, "WSAConnect");
m.insert(34, "WSACreateEvent");
m.insert(35, "WSADuplicateSocketA");
m.insert(36, "WSADuplicateSocketW");
m.insert(37, "WSAEnumNameSpaceProvidersA");
m.insert(38, "WSAEnumNameSpaceProvidersW");
m.insert(39, "WSAEnumNetworkEvents");
m.insert(40, "WSAEnumProtocolsA");
m.insert(41, "WSAEnumProtocolsW");
m.insert(42, "WSAEventSelect");
m.insert(43, "WSAGetOverlappedResult");
m.insert(44, "WSAGetQOSByName");
m.insert(45, "WSAGetServiceClassInfoA");
m.insert(46, "WSAGetServiceClassInfoW");
m.insert(47, "WSAGetServiceClassNameByClassIdA");
m.insert(48, "WSAGetServiceClassNameByClassIdW");
m.insert(49, "WSAHtonl");
m.insert(50, "WSAHtons");
m.insert(51, "gethostbyaddr");
m.insert(52, "gethostbyname");
m.insert(53, "getprotobyname");
m.insert(54, "getprotobynumber");
m.insert(55, "getservbyname");
m.insert(56, "getservbyport");
m.insert(57, "gethostname");
m.insert(58, "WSAInstallServiceClassA");
m.insert(59, "WSAInstallServiceClassW");
m.insert(60, "WSAIoctl");
m.insert(61, "WSAJoinLeaf");
m.insert(62, "WSALookupServiceBeginA");
m.insert(63, "WSALookupServiceBeginW");
m.insert(64, "WSALookupServiceEnd");
m.insert(65, "WSALookupServiceNextA");
m.insert(66, "WSALookupServiceNextW");
m.insert(67, "WSANSPIoctl");
m.insert(68, "WSANtohl");
m.insert(69, "WSANtohs");
m.insert(70, "WSAProviderConfigChange");
m.insert(71, "WSARecv");
m.insert(72, "WSARecvDisconnect");
m.insert(73, "WSARecvFrom");
m.insert(74, "WSARemoveServiceClass");
m.insert(75, "WSAResetEvent");
m.insert(76, "WSASend");
m.insert(77, "WSASendDisconnect");
m.insert(78, "WSASendTo");
m.insert(79, "WSASetEvent");
m.insert(80, "WSASetServiceA");
m.insert(81, "WSASetServiceW");
m.insert(82, "WSASocketA");
m.insert(83, "WSASocketW");
m.insert(84, "WSAStringToAddressA");
m.insert(85, "WSAStringToAddressW");
m.insert(86, "WSAWaitForMultipleEvents");
m.insert(87, "WSCDeinstallProvider");
m.insert(88, "WSCEnableNSProvider");
m.insert(89, "WSCEnumProtocols");
m.insert(90, "WSCGetProviderPath");
m.insert(91, "WSCInstallNameSpace");
m.insert(92, "WSCInstallProvider");
m.insert(93, "WSCUnInstallNameSpace");
m.insert(94, "WSCUpdateProvider");
m.insert(95, "WSCWriteNameSpaceOrder");
m.insert(96, "WSCWriteProviderOrder");
m.insert(97, "freeaddrinfo");
m.insert(98, "getaddrinfo");
m.insert(99, "getnameinfo");
m.insert(101, "WSAAsyncSelect");
m.insert(102, "WSAAsyncGetHostByAddr");
m.insert(103, "WSAAsyncGetHostByName");
m.insert(104, "WSAAsyncGetProtoByNumber");
m.insert(105, "WSAAsyncGetProtoByName");
m.insert(106, "WSAAsyncGetServByPort");
m.insert(107, "WSAAsyncGetServByName");
m.insert(108, "WSACancelAsyncRequest");
m.insert(109, "WSASetBlockingHook");
m.insert(110, "WSAUnhookBlockingHook");
m.insert(111, "WSAGetLastError");
m.insert(112, "WSASetLastError");
m.insert(113, "WSACancelBlockingCall");
m.insert(114, "WSAIsBlocking");
m.insert(115, "WSAStartup");
m.insert(116, "WSACleanup");
m.insert(151, "__WSAFDIsSet");
m.insert(500, "WEP");
m
});

m.get(&ordinal).copied()
match ordinal {
1 => Some("accept"),
2 => Some("bind"),
3 => Some("closesocket"),
4 => Some("connect"),
5 => Some("getpeername"),
6 => Some("getsockname"),
7 => Some("getsockopt"),
8 => Some("htonl"),
9 => Some("htons"),
10 => Some("ioctlsocket"),
11 => Some("inet_addr"),
12 => Some("inet_ntoa"),
13 => Some("listen"),
14 => Some("ntohl"),
15 => Some("ntohs"),
16 => Some("recv"),
17 => Some("recvfrom"),
18 => Some("select"),
19 => Some("send"),
20 => Some("sendto"),
21 => Some("setsockopt"),
22 => Some("shutdown"),
23 => Some("socket"),
24 => Some("GetAddrInfoW"),
25 => Some("GetNameInfoW"),
26 => Some("WSApSetPostRoutine"),
27 => Some("FreeAddrInfoW"),
28 => Some("WPUCompleteOverlappedRequest"),
29 => Some("WSAAccept"),
30 => Some("WSAAddressToStringA"),
31 => Some("WSAAddressToStringW"),
32 => Some("WSACloseEvent"),
33 => Some("WSAConnect"),
34 => Some("WSACreateEvent"),
35 => Some("WSADuplicateSocketA"),
36 => Some("WSADuplicateSocketW"),
37 => Some("WSAEnumNameSpaceProvidersA"),
38 => Some("WSAEnumNameSpaceProvidersW"),
39 => Some("WSAEnumNetworkEvents"),
40 => Some("WSAEnumProtocolsA"),
41 => Some("WSAEnumProtocolsW"),
42 => Some("WSAEventSelect"),
43 => Some("WSAGetOverlappedResult"),
44 => Some("WSAGetQOSByName"),
45 => Some("WSAGetServiceClassInfoA"),
46 => Some("WSAGetServiceClassInfoW"),
47 => Some("WSAGetServiceClassNameByClassIdA"),
48 => Some("WSAGetServiceClassNameByClassIdW"),
49 => Some("WSAHtonl"),
50 => Some("WSAHtons"),
51 => Some("gethostbyaddr"),
52 => Some("gethostbyname"),
53 => Some("getprotobyname"),
54 => Some("getprotobynumber"),
55 => Some("getservbyname"),
56 => Some("getservbyport"),
57 => Some("gethostname"),
58 => Some("WSAInstallServiceClassA"),
59 => Some("WSAInstallServiceClassW"),
60 => Some("WSAIoctl"),
61 => Some("WSAJoinLeaf"),
62 => Some("WSALookupServiceBeginA"),
63 => Some("WSALookupServiceBeginW"),
64 => Some("WSALookupServiceEnd"),
65 => Some("WSALookupServiceNextA"),
66 => Some("WSALookupServiceNextW"),
67 => Some("WSANSPIoctl"),
68 => Some("WSANtohl"),
69 => Some("WSANtohs"),
70 => Some("WSAProviderConfigChange"),
71 => Some("WSARecv"),
72 => Some("WSARecvDisconnect"),
73 => Some("WSARecvFrom"),
74 => Some("WSARemoveServiceClass"),
75 => Some("WSAResetEvent"),
76 => Some("WSASend"),
77 => Some("WSASendDisconnect"),
78 => Some("WSASendTo"),
79 => Some("WSASetEvent"),
80 => Some("WSASetServiceA"),
81 => Some("WSASetServiceW"),
82 => Some("WSASocketA"),
83 => Some("WSASocketW"),
84 => Some("WSAStringToAddressA"),
85 => Some("WSAStringToAddressW"),
86 => Some("WSAWaitForMultipleEvents"),
87 => Some("WSCDeinstallProvider"),
88 => Some("WSCEnableNSProvider"),
89 => Some("WSCEnumProtocols"),
90 => Some("WSCGetProviderPath"),
91 => Some("WSCInstallNameSpace"),
92 => Some("WSCInstallProvider"),
93 => Some("WSCUnInstallNameSpace"),
94 => Some("WSCUpdateProvider"),
95 => Some("WSCWriteNameSpaceOrder"),
96 => Some("WSCWriteProviderOrder"),
97 => Some("freeaddrinfo"),
98 => Some("getaddrinfo"),
99 => Some("getnameinfo"),
101 => Some("WSAAsyncSelect"),
102 => Some("WSAAsyncGetHostByAddr"),
103 => Some("WSAAsyncGetHostByName"),
104 => Some("WSAAsyncGetProtoByNumber"),
105 => Some("WSAAsyncGetProtoByName"),
106 => Some("WSAAsyncGetServByPort"),
107 => Some("WSAAsyncGetServByName"),
108 => Some("WSACancelAsyncRequest"),
109 => Some("WSASetBlockingHook"),
110 => Some("WSAUnhookBlockingHook"),
111 => Some("WSAGetLastError"),
112 => Some("WSASetLastError"),
113 => Some("WSACancelBlockingCall"),
114 => Some("WSAIsBlocking"),
115 => Some("WSAStartup"),
116 => Some("WSACleanup"),
151 => Some("__WSAFDIsSet"),
500 => Some("WEP"),
_ => None,
}
}
11 changes: 5 additions & 6 deletions lib/src/modules/vba/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/575462ba
*/

use crate::modules::vba::parser::decompress_stream;
use std::collections::HashMap;
use rustc_hash::FxHashMap as HashMap;

use crate::mods::prelude::*;
use crate::modules::olecf::parser::OLECFParser;
Expand Down Expand Up @@ -41,24 +41,23 @@ impl<'a> VbaExtractor<'a> {
let stream_names = ole_parser.get_stream_names()?;

let mut vba_dir = None;
let mut modules = HashMap::new();
let mut modules = HashMap::default();

// First process the dir stream
if let Some(dir_name) =
stream_names.iter().find(|n| n.to_lowercase().trim() == "dir")
stream_names.iter().find(|n| n.trim().eq_ignore_ascii_case("dir"))
&& let Ok(data) = Self::read_stream_data(&ole_parser, dir_name)
{
vba_dir = Some(data);
}

// Then process other streams
for name in &stream_names {
let lowercase_name = name.to_lowercase();

if lowercase_name != "dir"
if !name.trim().eq_ignore_ascii_case("dir")
&& let Ok(data) = Self::read_stream_data(&ole_parser, name)
&& !data.is_empty()
{
let lowercase_name = name.to_lowercase();
modules.insert(parser::normalize_name(&lowercase_name), data);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/modules/vba/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap as HashMap;

use nom::combinator::opt;
use nom::multi::length_data;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/re/thompson/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ matches the regexp left-to-right, and another one that matches right-to-left.
*/

use itertools::Itertools;
use std::collections::HashMap;
use rustc_hash::FxHashMap as HashMap;
use std::collections::hash_map::Entry;
use std::fmt::{Display, Formatter};
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
Expand Down Expand Up @@ -322,7 +322,7 @@ impl Compiler {
// All chunks in `last_n_chucks` will be appended to the backward code
// in reverse order. The offset where each chunk resides in the backward
// code is stored in the hash map.
let mut chunk_locations = HashMap::new();
let mut chunk_locations = HashMap::default();

for (location, chunk) in
zip(locations.iter_mut(), last_n_chunks.iter()).rev()
Expand Down Expand Up @@ -1975,7 +1975,7 @@ fn optimize_seq(mut seq: Seq) -> Option<Seq> {
// literal. For instance, if the sequence contains literals `01 02 03` and
// `01 02 04`, the key `01 02` will contain a bitmap where bits 3 and 4
// are set, while the rest of the bits are unset.
let mut map = HashMap::new();
let mut map = HashMap::default();

for lit in literals {
// `prefix` contains all bytes in the literal except the last one.
Expand Down
Loading
Loading