Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OLE CF and VBA modules implemented #274

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
14 changes: 14 additions & 0 deletions cli/src/commands/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ enum SupportedModules {
Elf,
Pe,
Dotnet,
Olecf,
Vba
}

#[derive(Debug, Clone, ValueEnum)]
Expand Down Expand Up @@ -111,6 +113,12 @@ pub fn exec_dump(args: &ArgMatches) -> anyhow::Result<()> {
if !requested_modules.contains(&&SupportedModules::Pe) {
module_output.pe = MessageField::none()
}
if !requested_modules.contains(&&SupportedModules::Olecf) {
module_output.olecf = MessageField::none()
}
if !requested_modules.contains(&&SupportedModules::Vba) {
module_output.vba = MessageField::none()
}
} else {
// Module was not specified, only show those that produced meaningful
// results, the rest are cleared out.
Expand All @@ -131,6 +139,12 @@ pub fn exec_dump(args: &ArgMatches) -> anyhow::Result<()> {
if !module_output.pe.is_pe() {
module_output.pe = MessageField::none()
}
if !module_output.olecf.is_olecf() {
module_output.olecf = MessageField::none()
}
if !module_output.vba.has_macros() {
module_output.vba = MessageField::none()
}
}

match output_format {
Expand Down
9 changes: 9 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ magic-module = [
# The `math` module.
math-module = []

# The `olecf` module
olecf-module = []

# The `pe` module parses PE files.
pe-module = [
"dep:const-oid",
Expand Down Expand Up @@ -182,6 +185,9 @@ text-module = [
# conditions of a rule to check against other epoch time.
time-module = []

# The `vba` module
vba-module = []

# Features that are enabled by default.
default = [
"constant-folding",
Expand All @@ -194,10 +200,12 @@ default = [
"macho-module",
"math-module",
"hash-module",
"olecf-module",
"pe-module",
"string-module",
"time-module",
"lnk-module",
"vba-module",
"test_proto2-module",
"test_proto3-module",
]
Expand Down Expand Up @@ -260,6 +268,7 @@ x509-parser = { workspace = true, optional = true }
yansi = { workspace = true }
yara-x-macros = { workspace = true }
yara-x-parser = { workspace = true, features = ["serde"] }
zip = { workspace = true }

lingua = { version = "1.6.2", optional = true, default-features = false, features = ["english", "german", "french", "spanish"] }

Expand Down
4 changes: 4 additions & 0 deletions lib/src/modules/add_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ add_module!(modules, "macho", macho, "macho.Macho", Some("macho"), Some(macho::_
add_module!(modules, "magic", magic, "magic.Magic", Some("magic"), Some(magic::__main__ as MainFn));
#[cfg(feature = "math-module")]
add_module!(modules, "math", math, "math.Math", Some("math"), Some(math::__main__ as MainFn));
#[cfg(feature = "olecf-module")]
add_module!(modules, "olecf", olecf, "olecf.Olecf", Some("olecf"), Some(olecf::__main__ as MainFn));
#[cfg(feature = "pe-module")]
add_module!(modules, "pe", pe, "pe.PE", Some("pe"), Some(pe::__main__ as MainFn));
#[cfg(feature = "string-module")]
Expand All @@ -30,4 +32,6 @@ add_module!(modules, "test_proto3", test_proto3, "test_proto3.TestProto3", Some(
add_module!(modules, "text", text, "text.Text", Some("text"), Some(text::__main__ as MainFn));
#[cfg(feature = "time-module")]
add_module!(modules, "time", time, "time.Time", Some("time"), Some(time::__main__ as MainFn));
#[cfg(feature = "vba-module")]
add_module!(modules, "vba", vba, "vba.Vba", Some("vba"), Some(vba::__main__ as MainFn));
}
20 changes: 20 additions & 0 deletions lib/src/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ pub mod mods {
/// Data structure returned by the `macho` module.
pub use super::protos::macho::Macho;

/// Data structures defined by the `olecf` module.
///
/// The main structure produced by the module is [`olecf:Olecf`]. The rest
/// of them are used by one or more fields in the main structure.
///
pub use super::protos::olecf;
/// Data structure returned by the `olecf` module.
pub use super::protos::olecf::Olecf;

/// Data structures defined by the `vba` module.
///
/// The main structure produced by the module is [`vba::Vba`]. The rest
/// of them are used by one or more fields in the main structure.
///
pub use super::protos::vba;
/// Data structure returned by the `macho` module.
pub use super::protos::vba::Vba;

/// Data structures defined by the `pe` module.
///
/// The main structure produced by the module is [`pe::PE`]. The rest
Expand Down Expand Up @@ -268,6 +286,8 @@ pub mod mods {
info.dotnet = protobuf::MessageField(invoke::<Dotnet>(data));
info.macho = protobuf::MessageField(invoke::<Macho>(data));
info.lnk = protobuf::MessageField(invoke::<Lnk>(data));
info.olecf = protobuf::MessageField(invoke::<Olecf>(data));
info.vba = protobuf::MessageField(invoke::<Vba>(data));
info
}

Expand Down
6 changes: 5 additions & 1 deletion lib/src/modules/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mod macho;
mod magic;
#[cfg(feature = "math-module")]
mod math;
#[cfg(feature = "olecf-module")]
mod olecf;
#[cfg(feature = "pe-module")]
mod pe;
#[cfg(feature = "string-module")]
Expand All @@ -28,4 +30,6 @@ mod test_proto3;
#[cfg(feature = "text-module")]
mod text;
#[cfg(feature = "time-module")]
mod time;
mod time;
#[cfg(feature = "vba-module")]
mod vba;
50 changes: 50 additions & 0 deletions lib/src/modules/olecf/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*! YARA module that parses OLE Compound File Binary Format files.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include some links to documentation explaining the format.

The OLE CF format (also known as Compound File Binary Format or CFBF) is a
container format used by many Microsoft file formats including DOC, XLS, PPT,
and MSI. This module specializes in parsing OLE CF files and extracting
metadata about their structure and contents.
*/

use crate::modules::prelude::*;
use crate::modules::protos::olecf::*;
pub mod parser;

#[module_main]
fn main(data: &[u8], _meta: Option<&[u8]>) -> Olecf {

match parser::OLECFParser::new(data) {
Ok(parser) => {
let mut olecf = Olecf::new();

// Check and set is_olecf
let is_valid = parser.is_valid_header();
olecf.is_olecf = Some(is_valid);

// Get stream names and sizes
match parser.get_stream_names() {
Ok(names) => {
// Get sizes for each stream
olecf.stream_sizes = names.iter()
.filter_map(|name| {
parser.get_stream_size(name)
.ok()
.map(|size| size as i64)
})
.collect();

// Assign names last after we're done using them
olecf.stream_names = names;
},
Err(_) => (),
}

olecf
},
Err(_) => {
let mut olecf = Olecf::new();
olecf.is_olecf = Some(false);
olecf
}
}
}
Loading
Loading